diff --git a/Cargo.lock b/Cargo.lock index 007567b5..d0a95294 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,61 +18,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" -[[package]] -name = "accesskit" -version = "0.22.0" -source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" -dependencies = [ - "uuid", -] - -[[package]] -name = "accesskit_consumer" -version = "0.32.0" -source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" -dependencies = [ - "accesskit", - "hashbrown 0.16.1", -] - -[[package]] -name = "accesskit_macos" -version = "0.23.0" -source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "accesskit_windows" -version = "0.30.0" -source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "static_assertions", - "windows 0.61.3", - "windows-core 0.61.2", -] - -[[package]] -name = "accesskit_winit" -version = "0.30.0" -source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" -dependencies = [ - "accesskit", - "accesskit_macos", - "accesskit_windows", - "raw-window-handle", - "winit 0.31.0-beta.2", -] - [[package]] name = "addr2line" version = "0.25.1" @@ -116,12 +61,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - [[package]] name = "almost" version = "0.2.0" @@ -135,7 +74,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.13.1", + "bitflags 2.11.0", "cc", "cesu8", "jni", @@ -182,15 +121,6 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f47b57fc4521e3cae26a4d45b5227f8fadee4c345be0fefd8d5d1711afb8aeb9" -[[package]] -name = "approx" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" -dependencies = [ - "num-traits", -] - [[package]] name = "approx" version = "0.5.1" @@ -236,25 +166,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "ashpd" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a3c86f3fd70c0ffa500ed189abfa90b5a52398a45d5dc372fcc38ebeb7a645" -dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.9.2", - "serde", - "serde_repr", - "url", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "zbus", -] - [[package]] name = "async-broadcast" version = "0.7.2" @@ -432,7 +343,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -479,9 +390,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -501,22 +412,13 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", -] - [[package]] name = "block2" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "objc2 0.6.4", + "objc2", ] [[package]] @@ -561,13 +463,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "build_helpers" -version = "0.14.0" -dependencies = [ - "cfg_aliases", -] - [[package]] name = "bumpalo" version = "3.20.2" @@ -619,7 +514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ "async-task", - "bitflags 2.13.1", + "bitflags 2.11.0", "futures-core", "polling", "rustix 1.1.4", @@ -679,16 +574,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "cgmath" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a98d30140e3296250832bbaaff83b27dcd6fa3cc70fb6f1f3e5c9c0023b5317" -dependencies = [ - "approx 0.4.0", - "num-traits", -] - [[package]] name = "chacha20" version = "0.10.0" @@ -709,7 +594,7 @@ dependencies = [ "iana-time-zone", "num-traits", "serde", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -730,6 +615,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", @@ -739,12 +625,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 = "cocoa" version = "0.25.0" @@ -754,7 +650,7 @@ dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", - "core-foundation 0.9.4", + "core-foundation", "core-graphics", "foreign-types", "libc", @@ -769,8 +665,8 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", + "core-foundation", + "core-graphics-types", "libc", "objc", ] @@ -781,9 +677,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ - "serde", - "termcolor", - "unicode-width 0.1.14", + "unicode-width", ] [[package]] @@ -827,16 +721,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -850,8 +734,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", + "core-foundation", + "core-graphics-types", "foreign-types", "libc", ] @@ -863,18 +747,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.13.1", - "core-foundation 0.10.1", + "core-foundation", "libc", ] @@ -887,24 +760,12 @@ dependencies = [ "libm", ] -[[package]] -name = "cosmic-client-toolkit" -version = "0.2.0" -dependencies = [ - "bitflags 2.13.1", - "cosmic-protocols", - "libc", - "smithay-client-toolkit", - "wayland-client", - "wayland-protocols", -] - [[package]] name = "cosmic-comp" version = "1.0.0" dependencies = [ "anyhow", - "bitflags 2.13.1", + "bitflags 2.11.0", "calloop", "clap_lex", "cosmic-comp-config", @@ -926,7 +787,7 @@ dependencies = [ "indexmap 2.13.0", "jiff", "keyframe", - "libcosmic-yoda", + "libcosmic", "libdisplay-info", "libsystemd", "log-panics", @@ -948,7 +809,7 @@ dependencies = [ "smithay", "smithay-egui", "thiserror 2.0.18", - "tiny-skia 0.11.4", + "tiny-skia", "tracing", "tracing-journald", "tracing-subscriber", @@ -978,6 +839,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "1.0.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "atomicwrites", "calloop", @@ -998,6 +860,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "1.0.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "quote", "syn", @@ -1006,11 +869,12 @@ dependencies = [ [[package]] name = "cosmic-freedesktop-icons" version = "0.4.0" +source = "git+https://github.com/pop-os/freedesktop-icons#ab4c57b8e416c6af9297cb04d101889896fd9a92" dependencies = [ "bstr", "btoi", "memchr", - "memmap2 0.9.10", + "memmap2", "thiserror 2.0.18", "tracing", "xdg", @@ -1019,10 +883,10 @@ dependencies = [ [[package]] name = "cosmic-protocols" version = "0.2.0" +source = "git+https://github.com/pop-os//cosmic-protocols?branch=main#32283d76a8d0342da74c4cc022a533c52dcf378f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", - "wayland-client", "wayland-protocols", "wayland-protocols-wlr", "wayland-scanner", @@ -1031,7 +895,8 @@ dependencies = [ [[package]] name = "cosmic-randr-shell" -version = "1.3.0" +version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-randr/#6e8e795970fa06d434af22775e415b517f7552d3" dependencies = [ "kdl", "slotmap", @@ -1041,6 +906,7 @@ dependencies = [ [[package]] name = "cosmic-settings-config" version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-settings-daemon#e37160f14d1e7ee428f973cd2848b4e95f83dfe1" dependencies = [ "cosmic-config", "ron 0.11.0", @@ -1052,7 +918,8 @@ dependencies = [ [[package]] name = "cosmic-settings-daemon" -version = "0.1.1-yoda.1" +version = "0.1.0" +source = "git+https://github.com/pop-os/dbus-settings-bindings#eed01dd3609e90e3c8cd043656734c500956c793" dependencies = [ "zbus", ] @@ -1060,6 +927,7 @@ dependencies = [ [[package]] name = "cosmic-settings-daemon-config" version = "0.1.0" +source = "git+https://github.com/pop-os/cosmic-settings-daemon#e37160f14d1e7ee428f973cd2848b4e95f83dfe1" dependencies = [ "cosmic-config", "cosmic-theme", @@ -1069,8 +937,10 @@ dependencies = [ [[package]] name = "cosmic-text" version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be17b688510d934ce13f48a2beba700e11583e281e0fda99c22bb256a14eda73" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "fontdb", "harfrust", "linebender_resource_handle", @@ -1086,12 +956,12 @@ dependencies = [ "unicode-linebreak", "unicode-script", "unicode-segmentation", - "unicode-width 0.2.2", ] [[package]] name = "cosmic-theme" version = "1.0.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "almost", "configparser", @@ -1148,6 +1018,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", @@ -1308,8 +1179,8 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.1", - "objc2 0.6.4", + "bitflags 2.11.0", + "objc2", ] [[package]] @@ -1335,8 +1206,9 @@ 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.13.1", + "bitflags 2.11.0", "mime 0.1.0", "raw-window-handle", "smithay-client-toolkit", @@ -1358,37 +1230,56 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" -[[package]] -name = "dpi" -version = "0.1.2" - [[package]] name = "dpi" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" +[[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 0.7.1", + "drm-fourcc", + "rustix 0.38.44", +] + [[package]] name = "drm" version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", - "drm-ffi", + "drm-ffi 0.9.1", "drm-fourcc", "libc", "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 0.6.1", + "rustix 0.38.44", +] + [[package]] name = "drm-ffi" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" dependencies = [ - "drm-sys", + "drm-sys 0.8.1", "rustix 1.1.4", ] @@ -1398,6 +1289,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 = "drm-sys" version = "0.8.1" @@ -1431,7 +1332,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" dependencies = [ "ahash", - "bitflags 2.13.1", + "bitflags 2.11.0", "emath", "epaint", "nohash-hasher", @@ -1797,7 +1698,7 @@ checksum = "457e789b3d1202543297a350643cf459f836cade38934e7a4cf6a39e7cde2905" dependencies = [ "fontconfig-parser", "log", - "memmap2 0.9.10", + "memmap2", "slotmap", "tinyvec", "ttf-parser", @@ -1955,8 +1856,8 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" dependencies = [ - "bitflags 2.13.1", - "drm", + "bitflags 2.11.0", + "drm 0.14.1", "drm-fourcc", "gbm-sys", "libc", @@ -1982,8 +1883,8 @@ dependencies = [ "libc", "log", "rustversion", - "windows-link 0.2.1", - "windows-result 0.4.1", + "windows-link", + "windows-result", ] [[package]] @@ -2003,7 +1904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ "rustix 1.1.4", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -2094,49 +1995,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "glutin_wgl_sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" -dependencies = [ - "gl_generator", -] - -[[package]] -name = "gpu-allocator" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51255ea7cfaadb6c5f1528d43e92a82acb2b96c43365989a28b2d44ee38f8795" -dependencies = [ - "ash", - "hashbrown 0.16.1", - "log", - "presser", - "thiserror 2.0.18", - "windows 0.62.2", -] - -[[package]] -name = "gpu-descriptor" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" -dependencies = [ - "bitflags 2.13.1", - "gpu-descriptor-types", - "hashbrown 0.15.5", -] - -[[package]] -name = "gpu-descriptor-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" -dependencies = [ - "bitflags 2.13.1", -] - [[package]] name = "grid" version = "1.0.0" @@ -2171,7 +2029,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f9f40651a03bc0f7316bd75267ff5767e93017ef3cfffe76c6aa7252cc5a31c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "core_maths", "read-fonts 0.37.0", @@ -2199,8 +2057,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", ] @@ -2348,7 +2204,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.62.2", + "windows-core", ] [[package]] @@ -2363,10 +2219,9 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "build_helpers", "dnd", - "iced_accessibility", "iced_core", "iced_debug", "iced_futures", @@ -2374,29 +2229,19 @@ dependencies = [ "iced_renderer", "iced_runtime", "iced_widget", - "iced_winit", "image", "mime 0.1.0", "thiserror 2.0.18", "window_clipboard", ] -[[package]] -name = "iced_accessibility" -version = "0.1.0" -dependencies = [ - "accesskit", - "accesskit_winit", -] - [[package]] name = "iced_core" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "bitflags 2.13.1", - "build_helpers", + "bitflags 2.11.0", "bytes", - "cosmic-client-toolkit", "dnd", "glam 0.25.0", "lilt", @@ -2417,6 +2262,7 @@ dependencies = [ [[package]] name = "iced_debug" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "iced_core", "iced_futures", @@ -2426,6 +2272,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "futures", "iced_core", @@ -2438,8 +2285,9 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "cosmic-text", "half", @@ -2458,6 +2306,7 @@ dependencies = [ [[package]] name = "iced_program" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "iced_graphics", "iced_runtime", @@ -2466,6 +2315,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -2477,10 +2327,9 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "build_helpers", "bytes", - "cosmic-client-toolkit", "dnd", "iced_core", "iced_futures", @@ -2492,6 +2341,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "bytemuck", "cosmic-text", @@ -2502,17 +2352,17 @@ dependencies = [ "resvg 0.45.1", "rustc-hash 2.1.1", "softbuffer", - "tiny-skia 0.11.4", + "tiny-skia", ] [[package]] name = "iced_wgpu" version = "0.14.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "bitflags 2.13.1", - "build_helpers", + "as-raw-xcb-connection", + "bitflags 2.11.0", "bytemuck", - "cosmic-client-toolkit", "cryoglyph", "futures", "glam 0.25.0", @@ -2526,19 +2376,20 @@ dependencies = [ "rustc-hash 2.1.1", "rustix 0.38.44", "thiserror 2.0.18", + "tiny-xlib", "wayland-backend", "wayland-client", "wayland-protocols", "wayland-sys", "wgpu", + "x11rb", ] [[package]] name = "iced_widget" version = "0.14.2" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ - "build_helpers", - "cosmic-client-toolkit", "dnd", "iced_renderer", "iced_runtime", @@ -2551,38 +2402,6 @@ dependencies = [ "window_clipboard", ] -[[package]] -name = "iced_winit" -version = "0.14.0" -dependencies = [ - "build_helpers", - "cosmic-client-toolkit", - "cursor-icon", - "dnd", - "iced_debug", - "iced_futures", - "iced_graphics", - "iced_program", - "iced_runtime", - "log", - "raw-window-handle", - "rustc-hash 2.1.1", - "rustix 0.38.44", - "thiserror 2.0.18", - "wasm-bindgen-futures", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "web-sys", - "winapi", - "window_clipboard", - "winit 0.31.0-beta.2", - "winit-core 0.31.0-beta.2", - "xkbcommon 0.7.0", - "xkbcommon-dl", - "xkeysym", -] - [[package]] name = "icu_collections" version = "2.1.1" @@ -2771,7 +2590,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "inotify-sys", "libc", ] @@ -2791,7 +2610,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9793345a65d71317763a33066b5d8351f8760dde8d4930fe9e39b5f14a7959d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "input-sys", "libc", "log", @@ -2949,7 +2768,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "serde", ] @@ -2963,17 +2782,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "khronos-egl" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" -dependencies = [ - "libc", - "libloading", - "pkg-config", -] - [[package]] name = "khronos_api" version = "3.1.0" @@ -3053,19 +2861,17 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" [[package]] -name = "libcosmic-yoda" -version = "0.1.0-yoda.2" +name = "libcosmic" +version = "1.0.0" +source = "git+https://github.com/pop-os/libcosmic#d922ac380134c00208d2acf93947d44fb217eec5" dependencies = [ "apply", - "ashpd", "auto_enums", - "build_helpers", - "cosmic-client-toolkit", "cosmic-config", "cosmic-freedesktop-icons", "cosmic-settings-daemon", @@ -3083,9 +2889,7 @@ dependencies = [ "iced_renderer", "iced_runtime", "iced_tiny_skia", - "iced_wgpu", "iced_widget", - "iced_winit", "image", "jiff", "log", @@ -3108,7 +2912,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59fd96dbb2381ff31f314f07accbdf8550febdcc5cd8761ecaf7c1763361c359" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "libc", "libdisplay-info-derive", "libdisplay-info-sys", @@ -3143,7 +2947,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -3154,14 +2958,13 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.20" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "libc", - "plain", - "redox_syscall 0.9.2", + "redox_syscall 0.7.2", ] [[package]] @@ -3233,6 +3036,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.9.4" @@ -3387,15 +3196,6 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" -[[package]] -name = "memmap2" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a5a03cefb0d953ec0be133036f14e109412fa594edc2f77227249db66cc3ed" -dependencies = [ - "libc", -] - [[package]] name = "memmap2" version = "0.9.10" @@ -3414,21 +3214,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "metal" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" -dependencies = [ - "bitflags 2.13.1", - "block", - "core-graphics-types 0.2.0", - "foreign-types", - "log", - "objc", - "paste", -] - [[package]] name = "miette" version = "7.6.0" @@ -3436,12 +3221,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" dependencies = [ "cfg-if", - "unicode-width 0.1.14", + "unicode-width", ] [[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", ] @@ -3482,9 +3268,9 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "mio" -version = "1.2.2" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", "log", @@ -3516,7 +3302,7 @@ checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.13.1", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "codespan-reporting", @@ -3529,7 +3315,6 @@ dependencies = [ "num-traits", "once_cell", "rustc-hash 1.1.0", - "spirv", "thiserror 2.0.18", "unicode-ident", ] @@ -3540,7 +3325,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "jni-sys", "log", "ndk-sys", @@ -3570,7 +3355,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -3598,7 +3383,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "fsevent-sys", "inotify", "kqueue", @@ -3616,7 +3401,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", ] [[package]] @@ -3750,22 +3535,6 @@ dependencies = [ "objc_id", ] -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - [[package]] name = "objc2" version = "0.6.4" @@ -3775,44 +3544,16 @@ dependencies = [ "objc2-encode", ] -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.13.1", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core", -] - [[package]] name = "objc2-app-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.1", - "objc2 0.6.4", + "bitflags 2.11.0", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.13.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", + "objc2-foundation", ] [[package]] @@ -3821,10 +3562,10 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", + "bitflags 2.11.0", + "block2", "dispatch2", - "objc2 0.6.4", + "objc2", ] [[package]] @@ -3833,30 +3574,18 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "libc", "objc2-core-foundation", ] -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", -] - [[package]] name = "objc2-core-video" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "objc2-core-foundation", "objc2-core-graphics", ] @@ -3867,65 +3596,28 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.13.1", - "block2 0.5.1", - "libc", - "objc2 0.5.2", -] - [[package]] name = "objc2-foundation" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", - "objc2 0.6.4", + "bitflags 2.11.0", + "block2", + "objc2", "objc2-core-foundation", ] -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.13.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.13.1", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", -] - [[package]] name = "objc2-ui-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.1", - "objc2 0.6.4", + "bitflags 2.11.0", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", + "objc2-foundation", ] [[package]] @@ -4026,7 +3718,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ - "approx 0.5.1", + "approx", "fast-srgb8", "palette_derive", "phf 0.11.3", @@ -4071,7 +3763,7 @@ dependencies = [ "libc", "redox_syscall 0.5.18", "smallvec", - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -4248,12 +3940,6 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" -[[package]] -name = "plain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" - [[package]] name = "png" version = "0.17.16" @@ -4273,7 +3959,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "crc32fast", "fdeflate", "flate2", @@ -4333,12 +4019,6 @@ dependencies = [ "zerocopy", ] -[[package]] -name = "presser" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" - [[package]] name = "prettyplease" version = "0.2.37" @@ -4468,20 +4148,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", - "rand_chacha 0.3.1", + "rand_chacha", "rand_core 0.6.4", ] -[[package]] -name = "rand" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.5", -] - [[package]] name = "rand" version = "0.10.0" @@ -4503,16 +4173,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.5", -] - [[package]] name = "rand_core" version = "0.6.4" @@ -4522,27 +4182,12 @@ dependencies = [ "getrandom 0.2.17", ] -[[package]] -name = "rand_core" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" -dependencies = [ - "getrandom 0.3.4", -] - [[package]] name = "rand_core" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" -[[package]] -name = "range-alloc" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" - [[package]] name = "rangemap" version = "1.7.1" @@ -4582,32 +4227,22 @@ dependencies = [ "font-types 0.11.0", ] -[[package]] -name = "redox_event" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15" -dependencies = [ - "bitflags 2.13.1", - "libredox", -] - [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.9.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1c93da5bb2c5d4e6c0ef7abeead62c89169a0a4882bfb83ac892f2423aea2fe" +checksum = "6d94dd2f7cd932d4dc02cc8b2b50dfd38bd079a4e5d79198b99743d7fcf9a4b4" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", ] [[package]] @@ -4698,7 +4333,7 @@ dependencies = [ "pico-args", "rgb", "svgtypes 0.13.0", - "tiny-skia 0.11.4", + "tiny-skia", "usvg 0.37.0", ] @@ -4714,7 +4349,7 @@ dependencies = [ "pico-args", "rgb", "svgtypes 0.15.3", - "tiny-skia 0.11.4", + "tiny-skia", "usvg 0.45.1", "zune-jpeg 0.4.21", ] @@ -4735,7 +4370,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468" dependencies = [ "base64 0.22.1", - "bitflags 2.13.1", + "bitflags 2.11.0", "serde", "serde_derive", "unicode-ident", @@ -4747,7 +4382,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "once_cell", "serde", "serde_derive", @@ -4825,7 +4460,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -4838,7 +4473,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -4857,7 +4492,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "core_maths", "log", @@ -4923,19 +4558,6 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sctk-adwaita" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2a4360b9abcdcee43809e6fc11d6d61ca5d25734026a8fc46c2883eea3f13f" -dependencies = [ - "ab_glyph", - "log", - "memmap2 0.9.10", - "smithay-client-toolkit", - "tiny-skia 0.12.0", -] - [[package]] name = "self_cell" version = "1.2.2" @@ -5150,20 +4772,20 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smithay" version = "0.7.0" -source = "git+https://github.com/smithay/smithay.git?rev=5fb12b8#5fb12b87407b3680135c45d94214c5f1b1d0fbea" +source = "git+https://github.com/smithay/smithay.git?rev=e3d461a#e3d461a057ba244d213a8498ec372b0799cca103" dependencies = [ "aliasable", "appendlist", "ash", - "bitflags 2.13.1", + "bitflags 2.11.0", "calloop", "cc", "cursor-icon", "downcast-rs", - "drm", - "drm-ffi", + "drm 0.14.1", + "drm-ffi 0.9.1", "drm-fourcc", - "drm-sys", + "drm-sys 0.8.1", "encoding_rs", "errno", "gbm", @@ -5179,7 +4801,7 @@ dependencies = [ "pkg-config", "portable-atomic", "profiling", - "rand 0.9.2", + "rand 0.10.0", "reis", "rustix 1.1.4", "scopeguard", @@ -5197,7 +4819,7 @@ dependencies = [ "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-server", - "winit 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winit", "x11rb", "xkbcommon 0.9.0", ] @@ -5208,15 +4830,13 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ - "bitflags 2.13.1", - "bytemuck", + "bitflags 2.11.0", "calloop", "calloop-wayland-source", "cursor-icon", "libc", "log", - "memmap2 0.9.10", - "pkg-config", + "memmap2", "rustix 1.1.4", "thiserror 2.0.18", "wayland-backend", @@ -5228,13 +4848,13 @@ dependencies = [ "wayland-protocols-misc", "wayland-protocols-wlr", "wayland-scanner", - "xkbcommon 0.8.0", "xkeysym", ] [[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", @@ -5245,16 +4865,13 @@ dependencies = [ [[package]] name = "smithay-egui" version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6794c95b83518f9f91ae8c2faee52302d521c0d541d016b4ed632374041d9c42" +source = "git+https://github.com/Smithay/smithay-egui.git?rev=6511552#65115521c756f356a7bcac8f1eeb715817a4666f" dependencies = [ - "cgmath", "egui", "egui_extras", "egui_glow", "image", "log", - "memoffset", "smithay", "xkbcommon 0.8.0", ] @@ -5278,20 +4895,22 @@ checksum = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1" [[package]] name = "softbuffer" version = "0.4.1" +source = "git+https://github.com/pop-os/softbuffer?tag=cosmic-4.0#c2b2c19ddb38ff17495643699f97cb1f2064a1be" dependencies = [ "as-raw-xcb-connection", "bytemuck", "cfg_aliases", "cocoa", "core-graphics", + "drm 0.11.1", "fastrand", "foreign-types", "js-sys", - "libredox", "log", - "memmap2 0.9.10", + "memmap2", "objc", "raw-window-handle", + "redox_syscall 0.5.18", "rustix 0.38.44", "tiny-xlib", "wasm-bindgen", @@ -5303,15 +4922,6 @@ dependencies = [ "x11rb", ] -[[package]] -name = "spirv" -version = "0.3.0+sdk-1.3.268.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" -dependencies = [ - "bitflags 2.13.1", -] - [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -5457,15 +5067,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -5558,21 +5159,7 @@ dependencies = [ "cfg-if", "log", "png 0.17.16", - "tiny-skia-path 0.11.4", -] - -[[package]] -name = "tiny-skia" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47ffee5eaaf5527f630fb0e356b90ebdec84d5d18d937c5e440350f88c5a91ea" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path 0.12.0", + "tiny-skia-path", ] [[package]] @@ -5586,17 +5173,6 @@ dependencies = [ "strict-num", ] -[[package]] -name = "tiny-skia-path" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca365c3faccca67d06593c5980fa6c57687de727a03131735bb85f01fdeeb9" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - [[package]] name = "tiny-xlib" version = "0.2.4" @@ -5937,12 +5513,6 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - [[package]] name = "unicode-xid" version = "0.2.6" @@ -5959,7 +5529,6 @@ dependencies = [ "idna", "percent-encoding", "serde", - "serde_derive", ] [[package]] @@ -5996,7 +5565,7 @@ dependencies = [ "siphasher 1.0.2", "strict-num", "svgtypes 0.15.3", - "tiny-skia-path 0.11.4", + "tiny-skia-path", "unicode-bidi", "unicode-script", "unicode-vo", @@ -6030,7 +5599,7 @@ dependencies = [ "rctree", "strict-num", "svgtypes 0.13.0", - "tiny-skia-path 0.11.4", + "tiny-skia-path", ] [[package]] @@ -6189,7 +5758,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap 2.13.0", "semver", @@ -6229,7 +5798,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "rustix 1.1.4", "wayland-backend", "wayland-scanner", @@ -6241,7 +5810,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "cursor-icon", "wayland-backend", ] @@ -6273,7 +5842,7 @@ version = "0.32.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -6286,7 +5855,7 @@ version = "20250721.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6299,7 +5868,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6313,7 +5882,7 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6326,7 +5895,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6351,7 +5920,7 @@ version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "downcast-rs", "rustix 1.1.4", "wayland-backend", @@ -6403,24 +5972,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" dependencies = [ "arrayvec", - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "cfg-if", "cfg_aliases", "document-features", "hashbrown 0.16.1", - "js-sys", "log", - "naga", - "parking_lot", "portable-atomic", "profiling", "raw-window-handle", "smallvec", "static_assertions", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", "wgpu-core", "wgpu-hal", "wgpu-types", @@ -6435,7 +5998,7 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "cfg_aliases", "document-features", @@ -6451,31 +6014,11 @@ dependencies = [ "rustc-hash 1.1.0", "smallvec", "thiserror 2.0.18", - "wgpu-core-deps-apple", - "wgpu-core-deps-emscripten", "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-types", ] -[[package]] -name = "wgpu-core-deps-apple" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b7b696b918f337c486bf93142454080a32a37832ba8a31e4f48221890047da" -dependencies = [ - "wgpu-hal", -] - -[[package]] -name = "wgpu-core-deps-emscripten" -version = "28.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34b251c331f84feac147de3c4aa3aa45112622a95dd7ee1b74384fa0458dbd79" -dependencies = [ - "wgpu-hal", -] - [[package]] name = "wgpu-core-deps-windows-linux-android" version = "28.0.0" @@ -6491,46 +6034,18 @@ version = "28.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44d6cb474beb218824dcc9e1ce679d973f719262789bfb27407da560cac20eeb" dependencies = [ - "android_system_properties", - "arrayvec", - "ash", - "bit-set", - "bitflags 2.13.1", - "block", - "bytemuck", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", - "core-graphics-types 0.2.0", - "glow", - "glutin_wgl_sys", - "gpu-allocator", - "gpu-descriptor", - "hashbrown 0.16.1", - "js-sys", - "khronos-egl", - "libc", "libloading", "log", - "metal", "naga", - "ndk-sys", - "objc", - "once_cell", - "ordered-float", - "parking_lot", "portable-atomic", "portable-atomic-util", - "profiling", - "range-alloc", "raw-window-handle", "renderdoc-sys", - "smallvec", "thiserror 2.0.18", - "wasm-bindgen", - "web-sys", "wgpu-types", - "windows 0.62.2", - "windows-core 0.62.2", ] [[package]] @@ -6539,7 +6054,7 @@ version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "js-sys", "log", @@ -6580,72 +6095,18 @@ 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", "thiserror 1.0.69", ] -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections 0.2.0", - "windows-core 0.61.2", - "windows-future 0.2.1", - "windows-link 0.1.3", - "windows-numerics 0.2.0", -] - -[[package]] -name = "windows" -version = "0.62.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" -dependencies = [ - "windows-collections 0.3.2", - "windows-core 0.62.2", - "windows-future 0.3.2", - "windows-numerics 0.3.1", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core 0.61.2", -] - -[[package]] -name = "windows-collections" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" -dependencies = [ - "windows-core 0.62.2", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings 0.4.2", -] - [[package]] name = "windows-core" version = "0.62.2" @@ -6654,31 +6115,9 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link 0.2.1", - "windows-result 0.4.1", - "windows-strings 0.5.1", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", - "windows-threading 0.1.0", -] - -[[package]] -name = "windows-future" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" -dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", - "windows-threading 0.2.1", + "windows-link", + "windows-result", + "windows-strings", ] [[package]] @@ -6703,63 +6142,19 @@ dependencies = [ "syn", ] -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core 0.61.2", - "windows-link 0.1.3", -] - -[[package]] -name = "windows-numerics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" -dependencies = [ - "windows-core 0.62.2", - "windows-link 0.2.1", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - [[package]] name = "windows-result" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", + "windows-link", ] [[package]] @@ -6768,7 +6163,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6822,7 +6217,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.1", + "windows-link", ] [[package]] @@ -6877,7 +6272,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link 0.2.1", + "windows-link", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -6888,24 +6283,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-threading" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" -dependencies = [ - "windows-link 0.2.1", -] - [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -7086,71 +6463,33 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" -[[package]] -name = "winit" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "cfg_aliases", - "cursor-icon", - "dpi 0.1.2", - "libc", - "raw-window-handle", - "rustix 1.1.4", - "smol_str", - "tracing", - "winit-android 0.31.0-beta.2", - "winit-appkit 0.31.0-beta.2", - "winit-common 0.31.0-beta.2", - "winit-core 0.31.0-beta.2", - "winit-orbital 0.31.0-beta.2", - "winit-uikit 0.31.0-beta.2", - "winit-wayland 0.31.0-beta.2", - "winit-web 0.31.0-beta.2", - "winit-win32 0.31.0-beta.2", -] - [[package]] name = "winit" version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "cfg_aliases", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "libc", "raw-window-handle", "rustix 1.1.4", "smol_str", "tracing", - "winit-android 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-appkit 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-common 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-orbital 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-uikit 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-wayland 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-web 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-win32 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winit-android", + "winit-appkit", + "winit-common", + "winit-core", + "winit-orbital", + "winit-uikit", + "winit-wayland", + "winit-web", + "winit-win32", "winit-x11", ] -[[package]] -name = "winit-android" -version = "0.31.0-beta.2" -dependencies = [ - "android-activity", - "bitflags 2.13.1", - "dpi 0.1.2", - "ndk", - "raw-window-handle", - "smol_str", - "tracing", - "winit-core 0.31.0-beta.2", -] - [[package]] name = "winit-android" version = "0.31.0-beta.2" @@ -7158,34 +6497,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df" dependencies = [ "android-activity", - "bitflags 2.13.1", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.11.0", + "dpi", "ndk", "raw-window-handle", "smol_str", "tracing", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-appkit" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", - "dispatch2", - "dpi 0.1.2", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-core-video", - "objc2-foundation 0.3.2", - "raw-window-handle", - "smol_str", - "tracing", - "winit-common 0.31.0-beta.2", - "winit-core 0.31.0-beta.2", + "winit-core", ] [[package]] @@ -7194,34 +6512,21 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", + "bitflags 2.11.0", + "block2", "dispatch2", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc2 0.6.4", - "objc2-app-kit 0.3.2", + "dpi", + "objc2", + "objc2-app-kit", "objc2-core-foundation", "objc2-core-graphics", "objc2-core-video", - "objc2-foundation 0.3.2", + "objc2-foundation", "raw-window-handle", "smol_str", "tracing", - "winit-common 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-common" -version = "0.31.0-beta.2" -dependencies = [ - "memmap2 0.9.10", - "objc2 0.6.4", - "objc2-core-foundation", - "smol_str", - "tracing", - "winit-core 0.31.0-beta.2", - "xkbcommon-dl", + "winit-common", + "winit-core", ] [[package]] @@ -7230,92 +6535,45 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45375fbac4cbb77260d83a30b1f9d8105880dbac99a9ae97f56656694680ff69" dependencies = [ - "memmap2 0.9.10", - "objc2 0.6.4", + "memmap2", + "objc2", "objc2-core-foundation", "smol_str", "tracing", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winit-core", "x11-dl", "xkbcommon-dl", ] -[[package]] -name = "winit-core" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "cursor-icon", - "dpi 0.1.2", - "keyboard-types", - "raw-window-handle", - "smol_str", - "web-time", -] - [[package]] name = "winit-core" version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "keyboard-types", "raw-window-handle", "smol_str", "web-time", ] -[[package]] -name = "winit-orbital" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "dpi 0.1.2", - "libredox", - "orbclient", - "raw-window-handle", - "redox_event", - "smol_str", - "tracing", - "winit-core 0.31.0-beta.2", -] - [[package]] name = "winit-orbital" version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46" dependencies = [ - "bitflags 2.13.1", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 2.11.0", + "dpi", "orbclient", "raw-window-handle", "redox_syscall 0.5.18", "smol_str", "tracing", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-uikit" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", - "dispatch2", - "dpi 0.1.2", - "objc2 0.6.4", - "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-ui-kit", - "raw-window-handle", - "smol_str", - "tracing", - "winit-common 0.31.0-beta.2", - "winit-core 0.31.0-beta.2", + "winit-core", ] [[package]] @@ -7324,44 +6582,19 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" dependencies = [ - "bitflags 2.13.1", - "block2 0.6.2", + "bitflags 2.11.0", + "block2", "dispatch2", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "objc2 0.6.4", + "dpi", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", + "objc2-foundation", "objc2-ui-kit", "raw-window-handle", "smol_str", "tracing", - "winit-common 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-wayland" -version = "0.31.0-beta.2" -dependencies = [ - "ahash", - "bitflags 2.13.1", - "calloop", - "cursor-icon", - "dpi 0.1.2", - "libc", - "memmap2 0.9.10", - "raw-window-handle", - "rustix 1.1.4", - "sctk-adwaita", - "smithay-client-toolkit", - "smol_str", - "tracing", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-plasma", - "winit-common 0.31.0-beta.2", - "winit-core 0.31.0-beta.2", + "winit-common", + "winit-core", ] [[package]] @@ -7371,12 +6604,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545" dependencies = [ "ahash", - "bitflags 2.13.1", + "bitflags 2.11.0", "calloop", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "libc", - "memmap2 0.9.10", + "memmap2", "raw-window-handle", "rustix 1.1.4", "smithay-client-toolkit", @@ -7386,29 +6619,8 @@ dependencies = [ "wayland-client", "wayland-protocols", "wayland-protocols-plasma", - "winit-common 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-web" -version = "0.31.0-beta.2" -dependencies = [ - "atomic-waker", - "bitflags 2.13.1", - "concurrent-queue", - "cursor-icon", - "dpi 0.1.2", - "js-sys", - "pin-project", - "raw-window-handle", - "smol_str", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "web-time", - "winit-core 0.31.0-beta.2", + "winit-common", + "winit-core", ] [[package]] @@ -7418,10 +6630,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92" dependencies = [ "atomic-waker", - "bitflags 2.13.1", + "bitflags 2.11.0", "concurrent-queue", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "js-sys", "pin-project", "raw-window-handle", @@ -7431,22 +6643,7 @@ dependencies = [ "wasm-bindgen-futures", "web-sys", "web-time", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winit-win32" -version = "0.31.0-beta.2" -dependencies = [ - "bitflags 2.13.1", - "cursor-icon", - "dpi 0.1.2", - "raw-window-handle", - "smol_str", - "tracing", - "unicode-segmentation", - "windows-sys 0.59.0", - "winit-core 0.31.0-beta.2", + "winit-core", ] [[package]] @@ -7455,15 +6652,15 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "raw-window-handle", "smol_str", "tracing", "unicode-segmentation", "windows-sys 0.59.0", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winit-core", ] [[package]] @@ -7472,19 +6669,19 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "bytemuck", "calloop", "cursor-icon", - "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dpi", "libc", "percent-encoding", "raw-window-handle", "rustix 1.1.4", "smol_str", "tracing", - "winit-common 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winit-core 0.31.0-beta.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winit-common", + "winit-core", "x11-dl", "x11rb", "xkbcommon-dl", @@ -7575,7 +6772,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.13.1", + "bitflags 2.11.0", "indexmap 2.13.0", "log", "serde", @@ -7666,17 +6863,6 @@ dependencies = [ "libc", ] -[[package]] -name = "xkbcommon" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13867d259930edc7091a6c41b4ce6eee464328c6ff9659b7e4c668ca20d4c91e" -dependencies = [ - "libc", - "memmap2 0.8.0", - "xkeysym", -] - [[package]] name = "xkbcommon" version = "0.8.0" @@ -7684,7 +6870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d66ca9352cbd4eecbbc40871d8a11b4ac8107cfc528a6e14d7c19c69d0e1ac9" dependencies = [ "libc", - "memmap2 0.9.10", + "memmap2", "xkeysym", ] @@ -7695,7 +6881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a974f48060a14e95705c01f24ad9c3345022f4d97441b8a36beb7ed5c4a02d" dependencies = [ "libc", - "memmap2 0.9.10", + "memmap2", "xkeysym", ] @@ -7705,7 +6891,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.13.1", + "bitflags 2.11.0", "dlib", "log", "once_cell", @@ -7717,9 +6903,6 @@ name = "xkeysym" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" -dependencies = [ - "bytemuck", -] [[package]] name = "xml-rs" @@ -7955,7 +7138,6 @@ dependencies = [ "endi", "enumflags2", "serde", - "url", "winnow 1.0.3", "zvariant_derive", "zvariant_utils", @@ -7986,7 +7168,3 @@ dependencies = [ "syn", "winnow 1.0.3", ] - -[[patch.unused]] -name = "winit-x11" -version = "0.31.0-beta.2" diff --git a/Cargo.toml b/Cargo.toml index 145f1248..11001e83 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -177,4 +177,5 @@ dnd = { path = "../window_clipboard/dnd" } mime = { path = "../window_clipboard/mime" } [patch.crates-io] -smithay = { git = "https://github.com/smithay/smithay.git", rev = "5fb12b8" } +smithay = { git = "https://github.com/smithay/smithay.git", rev = "e3d461a" } +smithay-egui = { git = "https://github.com/Smithay/smithay-egui.git", rev = "6511552" } diff --git a/cosmic-comp-config/src/lib.rs b/cosmic-comp-config/src/lib.rs index 853ba447..510927f9 100644 --- a/cosmic-comp-config/src/lib.rs +++ b/cosmic-comp-config/src/lib.rs @@ -66,6 +66,13 @@ impl Default for AppearanceConfig { } } +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +pub enum DecorationPreference { + #[default] + ClientSide, + ServerSide, +} + #[derive(Clone, Debug, PartialEq, CosmicConfigEntry)] #[version = 1] pub struct CosmicCompConfig { @@ -104,6 +111,7 @@ pub struct CosmicCompConfig { /// Briefly magnify the cursor when the pointer is shaken, to help locate it pub cursor_shake_to_find: bool, pub activation_policy: ActivationPolicy, + pub decoration_preference: DecorationPreference, } impl Default for CosmicCompConfig { @@ -143,6 +151,7 @@ impl Default for CosmicCompConfig { cursor_hide_timeout: None, cursor_shake_to_find: true, activation_policy: ActivationPolicy::default(), + decoration_preference: DecorationPreference::default(), } } } diff --git a/resources/i18n/fil/cosmic_comp.ftl b/resources/i18n/fil/cosmic_comp.ftl new file mode 100644 index 00000000..e69de29b diff --git a/resources/i18n/oc/cosmic_comp.ftl b/resources/i18n/oc/cosmic_comp.ftl index e69de29b..a1238332 100644 --- a/resources/i18n/oc/cosmic_comp.ftl +++ b/resources/i18n/oc/cosmic_comp.ftl @@ -0,0 +1,20 @@ +a11y-zoom-move-continuously = La vista bolega de contunh amb lo ponchador +a11y-zoom-move-onedge = La lista bolega quand lo ponchador atenh un caire +a11y-zoom-move-centered = La vista bolega per gardar lo ponchador al centre +a11y-zoom-settings = Paramètres de la lópia... +unknown-keybinding = +window-menu-tiled = Fenèstras bandejanta +window-menu-screenshot = Prendre una captura d’ecran +window-menu-resize = Redimensionar +window-menu-move-prev-workspace = Desplaçar a l’espaci de trabalh precedent +window-menu-move-next-workspace = Desplaçar a l'espaci de trabalh seguent +window-menu-stack = Crear una pila de fenèstras +window-menu-unstack-all = Desapilar totas las fenèstras +window-menu-unstack = Desapilar la fenèstra +window-menu-sticky = Fenèstra adesiva +window-menu-close = Tampar +window-menu-close-all = Tampar totas las fenèstras +window-menu-resize-edge-top = Amont +window-menu-resize-edge-left = Esquèrra +window-menu-resize-edge-right = Drecha +window-menu-resize-edge-bottom = Aval diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index 418a16f3..c58450bc 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -693,7 +693,7 @@ impl Device { ) .with_context(|| { format!( - "Failed to optain file descriptor for drm device: {}", + "Failed to obtain file descriptor for drm device: {}", path.display() ) })?, diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 6da04aac..36c6407c 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -32,7 +32,11 @@ use smithay::{ calloop::{Dispatcher, EventLoop, LoopHandle}, drm::{ Device as _, - control::{Device as _, connector::Interface, crtc}, + control::{ + Device as _, + connector::{Interface, State as ConnectorState}, + crtc, + }, }, input::{self, Libinput}, wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags, @@ -250,13 +254,18 @@ fn determine_primary_gpu( // try to find builtin display for dev in drm_devices.values() { - if dev.inner.surfaces.values().any(|s| { - if let Ok(conn_info) = dev.drm.device().get_connector(s.connector, false) { - let i = conn_info.interface(); - i == Interface::EmbeddedDisplayPort || i == Interface::LVDS || i == Interface::DSI - } else { - false - } + let drm = dev.drm.device(); + let res_handles = drm.resource_handles()?; + let connectors = res_handles.connectors(); + if connectors.iter().any(|conn| { + let Ok(conn_info) = drm.get_connector(*conn, false) else { + return false; + }; + let i = conn_info.interface(); + conn_info.state() == ConnectorState::Connected + && (i == Interface::EmbeddedDisplayPort + || i == Interface::LVDS + || i == Interface::DSI) }) { return Ok(Some(dev.inner.render_node)); } diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index b348640f..9ad61588 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -286,10 +286,10 @@ impl IndicatorShader { Uniform::new( "radius", [ - outer_radius[3] as f32, - outer_radius[1] as f32, outer_radius[0] as f32, + outer_radius[1] as f32, outer_radius[2] as f32, + outer_radius[3] as f32, ], ), Uniform::new("scale", scale as f32), @@ -899,8 +899,7 @@ where let geometry = geometry.to_local(output).as_logical(); let padded = with_states(layer.wl_surface(), |states| { - surface_padding(states, geometry.size) - .and_then(|padding| pad_rect(geometry, &padding)) + surface_padding(states).and_then(|padding| pad_rect(geometry, &padding)) }) .unwrap_or(geometry); let radii = with_states(layer.wl_surface(), |states| { diff --git a/src/backend/render/shadow.rs b/src/backend/render/shadow.rs index 37b1fdec..87fdd2e3 100644 --- a/src/backend/render/shadow.rs +++ b/src/backend/render/shadow.rs @@ -86,12 +86,6 @@ impl ShadowShader { let offset = [0., 5.]; let color = [0., 0., 0., if dark_mode { 0.45 } else { 0.35 }]; let radius = radius.map(|r| ceil(r as f64)); - let radius = [ - radius[3], // top_left - radius[1], // top_right - radius[0], // bottom_right - radius[2], // bottom_left - ]; let width = softness; let sigma = width / 2.; diff --git a/src/backend/render/wayland/blur_effect.rs b/src/backend/render/wayland/blur_effect.rs index c4d27fac..b8a7935a 100644 --- a/src/backend/render/wayland/blur_effect.rs +++ b/src/backend/render/wayland/blur_effect.rs @@ -247,10 +247,10 @@ impl BlurElement { Uniform::new( "corner_radius", [ - radii[3] as f32, - radii[1] as f32, radii[0] as f32, + radii[1] as f32, radii[2] as f32, + radii[3] as f32, ], ), Uniform::new( diff --git a/src/backend/render/wayland/clipped_surface.rs b/src/backend/render/wayland/clipped_surface.rs index 8322079e..52535269 100644 --- a/src/backend/render/wayland/clipped_surface.rs +++ b/src/backend/render/wayland/clipped_surface.rs @@ -99,10 +99,10 @@ where Uniform::new( "corner_radius", [ - radius[3] as f32, - radius[1] as f32, radius[0] as f32, + radius[1] as f32, radius[2] as f32, + radius[3] as f32, ], ), Uniform::new( @@ -145,10 +145,10 @@ where geo: Rectangle, radius: [u8; 4], ) -> [Rectangle; 4] { - let top_left = radius[3] as f64; + let top_left = radius[0] as f64; let top_right = radius[1] as f64; - let bottom_right = radius[0] as f64; - let bottom_left = radius[2] as f64; + let bottom_right = radius[2] as f64; + let bottom_left = radius[3] as f64; [ Rectangle::new(geo.loc, Size::from((top_left, top_left))), diff --git a/src/config/mod.rs b/src/config/mod.rs index 93b53374..4d2fad9b 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -14,8 +14,11 @@ use cosmic_config::{ConfigGet, CosmicConfigEntry}; use cosmic_settings_config::window_rules::ApplicationException; use cosmic_settings_config::{Shortcuts, shortcuts, window_rules}; use serde::{Deserialize, Serialize}; -use smithay::utils::{Clock, Monotonic}; use smithay::wayland::xdg_activation::XdgActivationState; +use smithay::{ + backend::input::InputTime, + utils::{Clock, Monotonic}, +}; pub use smithay::{ backend::input::{self as smithay_input, KeyState}, input::keyboard::{Keysym, ModifiersState, keysyms as KeySyms}, @@ -46,8 +49,8 @@ mod types; use cosmic::config::CosmicTk; pub use cosmic_comp_config::EdidProduct; use cosmic_comp_config::{ - ActivationPolicy, AppearanceConfig, CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig, - XwaylandDescaling, XwaylandEavesdropping, ZoomConfig, + ActivationPolicy, AppearanceConfig, CosmicCompConfig, DecorationPreference, KeyboardConfig, + TileBehavior, XkbConfig, XwaylandDescaling, XwaylandEavesdropping, ZoomConfig, input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride}, output::comp::{ OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef, load_outputs, @@ -538,7 +541,13 @@ impl Config { primary.config_mut().xwayland_primary = true; } } - for output in outputs.iter().filter(|o| o.mirroring().is_none()) { + // sort by connector name for a deterministic layout independent of hotplug order + let mut sorted_outputs = outputs + .iter() + .filter(|o| o.mirroring().is_none()) + .collect::>(); + sorted_outputs.sort_by_key(|o| o.name()); + for output in sorted_outputs { { let mut config = output.config_mut(); config.position = (w, 0); @@ -770,13 +779,12 @@ pub fn change_modifier_state( const X11_KEYCODE_OFFSET: u32 = 8; let mut input = |key_state, scan_code| { - let time = state.common.clock.now().as_millis(); let _ = keyboard.input( state, smithay_input::Keycode::new(scan_code + X11_KEYCODE_OFFSET), key_state, SERIAL_COUNTER.next_serial(), - time, + InputTime::now(), |_, _, _| smithay::input::keyboard::FilterResult::<()>::Forward, ); }; @@ -840,7 +848,9 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut } if !state.common.ei_seats.is_empty() { let seat = state.common.shell.read().seats.last_active().clone(); - state.broadcast_ei_keyboard_modifiers(&seat); + if let Some(keyboard) = seat.get_keyboard() { + state.broadcast_ei_keyboard_modifiers(&keyboard); + } } state.common.config.cosmic_conf.xkb_config = value; } @@ -998,6 +1008,13 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut state.common.config.cosmic_conf.activation_policy = new; } } + "decoration_preference" => { + let new = get_config::(&config, "decoration_preference"); + if new != state.common.config.cosmic_conf.decoration_preference { + state.common.config.cosmic_conf.decoration_preference = new; + state.update_decorations(); + } + } _ => {} } } diff --git a/src/input/actions.rs b/src/input/actions.rs index 8a5ef84c..8639ba62 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -18,6 +18,7 @@ use cosmic_config::ConfigSet; use cosmic_settings_config::shortcuts; use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection}; use smithay::{ + backend::input::InputTime, input::{Seat, pointer::MotionEvent}, utils::{Point, Serial}, }; @@ -45,7 +46,7 @@ impl State { backend_id: &InputBackendId, seat: &Seat, serial: Serial, - time: u32, + time: InputTime, pattern: shortcuts::Binding, direction: Option, ) { @@ -150,7 +151,7 @@ impl State { backend_id: &InputBackendId, seat: &Seat, serial: Serial, - time: u32, + time: InputTime, pattern: shortcuts::Binding, direction: Option, propagate: bool, diff --git a/src/input/mod.rs b/src/input/mod.rs index 0e307079..45586b03 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -9,7 +9,10 @@ use crate::{ cosmic_modifiers_from_smithay, }, }, - input::gestures::{GestureState, SwipeAction}, + input::{ + gestures::{GestureState, SwipeAction}, + tablet_emu::PointerEmulationGrab, + }, shell::{ SeatExt, Trigger, focus::{ @@ -42,19 +45,21 @@ use smithay::{ backend::input::{ AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, - GestureSwipeUpdateEvent as _, InputBackend, InputEvent, KeyState, PointerAxisEvent, - ProximityState, TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent, - TabletToolTipEvent, TabletToolTipState, TouchEvent, + GestureSwipeUpdateEvent as _, InputBackend, InputEvent, InputTime, KeyState, + PointerAxisEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, + TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent, }, desktop::{PopupKeyboardGrab, WindowSurfaceType, utils::under_from_surface_tree}, input::{ Seat, + keyboard::KeyboardHandle, keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, - PointerGrab, PointerHandle, RelativeMotionEvent, + AxisFrame, ButtonEvent as PointerButtonEvent, Focus, GestureHoldBeginEvent, + GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, + GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, + GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerGrab, PointerHandle, + RelativeMotionEvent, }, tablet::{TabletDescriptor, TabletSeatTrait, tool}, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, @@ -87,6 +92,7 @@ use std::{ pub mod actions; pub mod gestures; +pub mod tablet_emu; /// Identifies the input backend instance an event came from, used to disambiguate device ids /// (which are only unique within a single backend instance, see @@ -271,7 +277,7 @@ impl State { trace!(?keycode, ?state, "key"); let serial = SERIAL_COUNTER.next_serial(); - let time = Event::time_msec(&event); + let time = Event::time(&event); let keyboard = seat.get_keyboard().unwrap(); let previous_modifiers = keyboard.modifier_state(); if let Some((action, pattern)) = keyboard @@ -325,7 +331,7 @@ impl State { } InputEvent::PointerMotion { event, .. } => { - use smithay::backend::input::PointerMotionEvent; + use smithay::backend::input::PointerMotionEvent as _; let shell = self.common.shell.write(); if let Some(seat) = shell @@ -338,6 +344,9 @@ impl State { let current_output = seat.active_output(); if self.common.config.cosmic_conf.cursor_shake_to_find + && seat + .get_pointer() + .is_some_and(|pointer| !pointer.is_grabbed()) && let Some(cursor_state) = seat.user_data() .get::() @@ -397,7 +406,7 @@ impl State { &RelativeMotionEvent { delta: event.delta(), delta_unaccel: event.delta_unaccel(), - utime: event.time(), + time: event.time(), }, ); @@ -635,10 +644,10 @@ impl State { ptr.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial, - time: event.time_msec(), + time: event.time(), }, ); ptr.frame(self); @@ -750,23 +759,33 @@ impl State { ptr.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: position.as_logical(), serial, - time: event.time_msec(), + time: event.time(), }, ); ptr.frame(self); + let mut shell = self.common.shell.write(); // Keep the seat's active output following the pointer. Click-to- // focus (PointerButton) resolves its target via // `seat.active_output()` let previous_output = seat.active_output(); if previous_output != output { + for session in cursor_sessions_for_output(&shell, &previous_output) { + session.set_cursor_pos(None); + } seat.set_active_output(&output); } - let shell = self.common.shell.read(); + shell.update_pointer_position(position.to_local(&output), &output); + shell.update_focal_point( + &seat, + position, + self.common.config.cosmic_conf.accessibility_zoom.view_moves, + ); + update_output_image_copy_cursor_position( &shell, &self.common.clock, @@ -777,9 +796,8 @@ impl State { } } InputEvent::PointerButton { event, .. } => { - use smithay::backend::input::{ButtonState, PointerButtonEvent}; + use smithay::backend::input::{ButtonState, PointerButtonEvent as _}; - // let Some(seat) = self .common .shell @@ -853,7 +871,7 @@ impl State { && !shortcuts_inhibited { let seat_clone = seat.clone(); - let mouse_button = PointerButtonEvent::button(&event); + let mouse_button = event.button(); let mut supress_button = || { // If the logo is held then the pointer event is @@ -1005,7 +1023,7 @@ impl State { button, event.state(), serial, - event.time_msec(), + event.time(), ); } @@ -1013,16 +1031,16 @@ impl State { if pass_event { ptr.button( self, - &ButtonEvent { + &PointerButtonEvent { button, state: event.state(), serial, - time: event.time_msec(), + time: event.time(), }, ); ptr.frame(self); } else if event.state() == ButtonState::Released { - ptr.unset_grab(self, serial, event.time_msec()) + ptr.unset_grab(self, serial, event.time()) } } InputEvent::PointerAxis { event, .. } => { @@ -1073,7 +1091,7 @@ impl State { self.update_zoom(&seat, change, event.source() == AxisSource::Wheel); } } else { - let mut frame = AxisFrame::new(event.time_msec()).source(event.source()); + let mut frame = AxisFrame::new(event.time()).source(event.source()); let horizontal_amount = event .amount(Axis::Horizontal) .or_else(|| Some(event.amount_v120(Axis::Horizontal)? * 15.0 / 120.)); @@ -1142,7 +1160,7 @@ impl State { self, &GestureSwipeBeginEvent { serial, - time: event.time_msec(), + time: event.time(), fingers: event.fingers(), }, ); @@ -1163,7 +1181,7 @@ impl State { if let Some(ref mut gesture_state) = self.common.gesture_state { let first_update = gesture_state.update( event.delta(), - Duration::from_millis(event.time_msec() as u64), + Duration::from_millis(event.time().millis() as u64), ); // Decide on action if first update if first_update { @@ -1239,7 +1257,7 @@ impl State { pointer.gesture_swipe_update( self, &GestureSwipeUpdateEvent { - time: event.time_msec(), + time: event.time(), delta: event.delta(), }, ); @@ -1288,7 +1306,7 @@ impl State { self, &GestureSwipeEndEvent { serial, - time: event.time_msec(), + time: event.time(), cancelled: event.cancelled(), }, ); @@ -1311,7 +1329,7 @@ impl State { self, &GesturePinchBeginEvent { serial, - time: event.time_msec(), + time: event.time(), fingers: event.fingers(), }, ); @@ -1331,7 +1349,7 @@ impl State { pointer.gesture_pinch_update( self, &GesturePinchUpdateEvent { - time: event.time_msec(), + time: event.time(), delta: event.delta(), scale: event.scale(), rotation: event.rotation(), @@ -1355,7 +1373,7 @@ impl State { self, &GesturePinchEndEvent { serial, - time: event.time_msec(), + time: event.time(), cancelled: event.cancelled(), }, ); @@ -1377,7 +1395,7 @@ impl State { self, &GestureHoldBeginEvent { serial, - time: event.time_msec(), + time: event.time(), fingers: event.fingers(), }, ); @@ -1399,7 +1417,7 @@ impl State { self, &GestureHoldEndEvent { serial, - time: event.time_msec(), + time: event.time(), cancelled: event.cancelled(), }, ); @@ -1456,7 +1474,7 @@ impl State { slot: event.slot(), location: position.as_logical(), serial, - time: event.time_msec(), + time: event.time(), }, ); } @@ -1505,7 +1523,7 @@ impl State { &TouchMotionEvent { slot: event.slot(), location: position.as_logical(), - time: event.time_msec(), + time: event.time(), }, ); } @@ -1531,7 +1549,7 @@ impl State { self, &UpEvent { slot: event.slot(), - time: event.time_msec(), + time: event.time(), serial, }, ); @@ -1582,6 +1600,7 @@ impl State { return; }; + let current_output = seat.active_output(); let position = transform_output_mapped_position(&output, &event, shell.zoom_state()); let under = State::surface_under(position, &output, &shell) @@ -1590,21 +1609,33 @@ impl State { std::mem::drop(shell); let pointer = seat.get_pointer().unwrap(); - pointer.motion( - self, - under.clone(), - &MotionEvent { - location: position.as_logical(), - serial: SERIAL_COUNTER.next_serial(), - time: self.common.clock.now().as_millis(), - }, - ); + pointer.set_location(position.as_logical()); let tablet_seat = seat.tablet_seat(); let tool = tablet_seat.get_tool(&event.tool()); if let Some(tool) = tool { + let serial = SERIAL_COUNTER.next_serial(); + if !tool.is_grabbed() + && under + .as_ref() + .is_some_and(|(target, _)| !target.supports_tool(&tool)) + { + let start_data = tool::GrabStartData { + focus: under.clone(), + trigger: tool::GrabTrigger::Proximity, + location: position.as_logical(), + }; + tool.set_grab( + self, + PointerEmulationGrab::new(start_data, seat.clone()), + event.time(), + serial, + Focus::Keep, + ); + } + let frame = tool::AxisFrame { pressure: event.pressure_has_changed().then(|| event.pressure()), distance: event.distance_has_changed().then(|| event.distance()), @@ -1622,17 +1653,39 @@ impl State { tool.motion( self, - under - .and_then(|(f, loc)| f.wl_surface().map(|s| (s.into_owned(), loc))), + under, &tool::MotionEvent { location: position.as_logical(), - serial: SERIAL_COUNTER.next_serial(), - time: event.time_msec(), + serial, + time: event.time(), }, ); - tool.frame(self, event.time_msec()); + tool.frame(self, event.time()); } + + let mut shell = self.common.shell.write(); + shell.update_pointer_position(position.to_local(&output), &output); + shell.update_focal_point( + &seat, + position, + self.common.config.cosmic_conf.accessibility_zoom.view_moves, + ); + + if output != current_output { + for session in cursor_sessions_for_output(&shell, ¤t_output) { + session.set_cursor_pos(None); + } + seat.set_active_output(&output); + } + + update_output_image_copy_cursor_position( + &shell, + &self.common.clock, + &output, + &seat, + position, + ); } } InputEvent::TabletToolProximity { event, .. } => { @@ -1651,6 +1704,7 @@ impl State { return; }; + let current_output = seat.active_output(); let position = transform_output_mapped_position(&output, &event, shell.zoom_state()); let under = State::surface_under(position, &output, &shell) @@ -1659,15 +1713,7 @@ impl State { std::mem::drop(shell); let pointer = seat.get_pointer().unwrap(); - pointer.motion( - self, - under.clone(), - &MotionEvent { - location: position.as_logical(), - serial: SERIAL_COUNTER.next_serial(), - time: self.common.clock.now().as_millis(), - }, - ); + pointer.set_location(position.as_logical()); let tablet_seat = seat.tablet_seat(); @@ -1680,6 +1726,25 @@ impl State { if let Some(tablet) = tablet { let serial = SERIAL_COUNTER.next_serial(); + if !tool.is_grabbed() + && under + .as_ref() + .is_some_and(|(target, _)| !target.supports_tool(&tool)) + { + let start_data = tool::GrabStartData { + focus: under.clone(), + trigger: tool::GrabTrigger::Proximity, + location: position.as_logical(), + }; + tool.set_grab( + self, + PointerEmulationGrab::new(start_data, seat.clone()), + event.time(), + serial, + Focus::Keep, + ); + } + let frame = tool::AxisFrame { pressure: event.pressure_has_changed().then(|| event.pressure()), distance: event.distance_has_changed().then(|| event.distance()), @@ -1695,9 +1760,6 @@ impl State { match event.state() { ProximityState::In => { - let under = under.and_then(|(f, loc)| { - f.wl_surface().map(|s| (s.into_owned(), loc)) - }); tool.proximity_in( self, under, @@ -1705,25 +1767,75 @@ impl State { &tool::ProximityInEvent { location: position.as_logical(), axis: Some(frame), - serial: SERIAL_COUNTER.next_serial(), - time: event.time_msec(), + serial, + time: event.time(), }, - ) + ); + } + ProximityState::Out => { + tool.proximity_out( + self, + &tool::ProximityOutEvent { + serial, + time: event.time(), + }, + ); + if let Some(pointer) = seat.get_pointer() { + pointer.motion( + self, + None, + &PointerMotionEvent { + location: position.as_logical(), + serial, + time: event.time(), + }, + ); + } } - ProximityState::Out => tool.proximity_out( - self, - &tool::ProximityOutEvent { - serial, - time: event.time_msec(), - }, - ), } - tool.frame(self, event.time_msec()); + tool.frame(self, event.time()); + } + + if event.state() == ProximityState::In { + let mut shell = self.common.shell.write(); + shell.update_pointer_position(position.to_local(&output), &output); + shell.update_focal_point( + &seat, + position, + self.common.config.cosmic_conf.accessibility_zoom.view_moves, + ); + + if output != current_output { + for session in cursor_sessions_for_output(&shell, ¤t_output) { + session.set_cursor_pos(None); + } + seat.set_active_output(&output); + } + + update_output_image_copy_cursor_position( + &shell, + &self.common.clock, + &output, + &seat, + position, + ); } } } InputEvent::TabletToolTip { event, .. } => { + { + let mut shell = self.common.shell.write(); + if let Some(Trigger::Tool(desc, trigger)) = + shell.overview_mode().0.active_trigger() + && event.tool() == *desc + && matches!(*trigger, tool::GrabTrigger::Tip) + && event.tip_state() == TabletToolTipState::Up + { + shell.set_overview_mode(None, self.common.event_loop_handle.clone()); + } + } + let maybe_seat = self .common .shell @@ -1734,6 +1846,21 @@ impl State { if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); + + let serial = SERIAL_COUNTER.next_serial(); + let output = seat.active_output(); + let shell = self.common.shell.write(); + let position = + transform_output_mapped_position(&output, &event, shell.zoom_state()); + let under = State::element_under(position, &output, &shell, &seat); + drop(shell); + + if event.tip_state() == TabletToolTipState::Down + && let Some(target) = under.as_ref() + { + Shell::set_focus(self, Some(target), &seat, Some(serial), false); + } + if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { let serial = SERIAL_COUNTER.next_serial(); match event.tip_state() { @@ -1742,7 +1869,7 @@ impl State { self, &tool::DownEvent { serial, - time: event.time_msec(), + time: event.time(), }, ); } @@ -1751,13 +1878,13 @@ impl State { self, &tool::UpEvent { serial, - time: event.time_msec(), + time: event.time(), }, ); } } - tool.frame(self, event.time_msec()); + tool.frame(self, event.time()); } } } @@ -1779,11 +1906,11 @@ impl State { button: event.button(), state: event.button_state(), serial: SERIAL_COUNTER.next_serial(), - time: event.time_msec(), + time: event.time(), }, ); - tool.frame(self, event.time_msec()); + tool.frame(self, event.time()); } } } @@ -1886,7 +2013,7 @@ impl State { let Some(pointer) = seat.get_pointer() else { return; }; - let time = self.common.clock.now().as_millis(); + let time = InputTime::now(); for button in buttons { let serial = SERIAL_COUNTER.next_serial(); pointer.button( @@ -1904,13 +2031,7 @@ impl State { /// Mirror the seat's current modifier state to every libei sender with a keyboard via /// `ei_keyboard.modifiers` - pub(crate) fn broadcast_ei_keyboard_modifiers(&self, seat: &Seat) { - if self.common.ei_seats.is_empty() { - return; - } - let Some(keyboard) = seat.get_keyboard() else { - return; - }; + pub(crate) fn broadcast_ei_keyboard_modifiers(&self, keyboard: &KeyboardHandle) { let s = keyboard.modifier_state().serialized; for ei_seat in self.common.ei_seats.values() { ei_seat.keyboard_modifiers(s.depressed, s.locked, s.latched, s.layout_effective); @@ -1948,14 +2069,14 @@ impl State { modifiers: &ModifiersState, handle: KeysymHandle<'_>, serial: Serial, - time: u32, + time: InputTime, keycode: Keycode, key_state: KeyState, previous_modifiers: ModifiersState, ) -> FilterResult> { if previous_modifiers != *modifiers { seat.set_last_modifier_change(backend_id, serial); - self.broadcast_ei_keyboard_modifiers(seat); + self.broadcast_ei_keyboard_modifiers(&seat.get_keyboard().unwrap()); } let current_focus = seat.get_keyboard().unwrap().current_focus(); @@ -2008,7 +2129,7 @@ impl State { return; }; let serial = SERIAL_COUNTER.next_serial(); - let time = self.common.clock.now().as_millis(); + let time = InputTime::now(); let previous_modifiers = keyboard.modifier_state(); let result = keyboard .input_from_source( @@ -2157,7 +2278,7 @@ impl State { serial: Serial, keycode: Keycode, key_state: KeyState, - time: u32, + time: InputTime, ) -> FilterResult> { // Pre-compute for layout-agnostic shortcut matching let raw_syms = handle.raw_syms(); @@ -2322,7 +2443,9 @@ impl State { &backend_id_clone, &seat_clone, serial, - time.overflowing_add(duration as u32).0, + InputTime::from_millis( + time.millis().overflowing_add(duration as u32).0, + ), key_pattern_clone.clone(), None, ); @@ -2374,7 +2497,7 @@ impl State { self.common.event_loop_handle.insert_idle(move |state| { if let Some(keyboard) = seat.get_keyboard() { let serial = SERIAL_COUNTER.next_serial(); - let time = state.common.clock.now().as_millis(); + let time = InputTime::now(); keyboard.input( state, key_code, @@ -2900,6 +3023,7 @@ impl State { surface: &WlSurface, pointer: &PointerHandle, mut location: Point, + constraint: Option<&PointerConstraint>, ) { let Some(client) = surface.client() else { return; @@ -2924,15 +3048,13 @@ impl State { return false; } - with_pointer_constraint(surface, pointer, |constraint| { - if let Some(constraint) = constraint - && let Some(region) = constraint.region() - { - let point_in_surface = (p - surface_offset.to_f64()).to_i32_floor(); - return region.contains(point_in_surface); - } - true - }) + if let Some(constraint) = constraint + && let Some(region) = constraint.region() + { + let point_in_surface = (p - surface_offset.to_f64()).to_i32_floor(); + return region.contains(point_in_surface); + } + true }; let workspace_origin = output.geometry().loc.to_f64(); @@ -2956,23 +3078,23 @@ impl State { let serial = SERIAL_COUNTER.next_serial(); let under = State::surface_under(point, &output, &self.common.shell.write()) .map(|(target, pos)| (target, pos.as_logical())); - let time = self.common.clock.now(); + let time = InputTime::now(); pointer.relative_motion( self, under.clone(), &RelativeMotionEvent { delta: (0., 0.).into(), delta_unaccel: (0., 0.).into(), - utime: time.as_micros(), + time, }, ); pointer.motion( self, under, - &MotionEvent { + &PointerMotionEvent { location: point.as_logical(), serial, - time: time.as_millis(), + time, }, ); pointer.frame(self); diff --git a/src/input/tablet_emu.rs b/src/input/tablet_emu.rs new file mode 100644 index 00000000..6ab17924 --- /dev/null +++ b/src/input/tablet_emu.rs @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-3.0-only + +//! Pointer Emulating TabletTool grab. + +use crate::{shell::focus::target::PointerFocusTarget, state::State}; +use smithay::{ + backend::input::{ButtonState, InputTime, MouseButton}, + input::{ + Seat, pointer, + tablet::{ + self, + tool::{ + AxisFrame, ButtonEvent, DownEvent, GrabStartData, ProximityInEvent, + ProximityOutEvent, TabletToolGrab, TabletToolInnerHandle, UpEvent, + }, + }, + }, + utils::{Logical, Point, SERIAL_COUNTER}, +}; + +// from https://gitlab.freedesktop.org/libinput/libinput/-/blob/main/include/linux/linux/input-event-codes.h +const BTN_STYLUS: u32 = 0x14b; +const BTN_STYLUS_2: u32 = 0x14c; +const BTN_LEFT: u32 = 0x110; +const BTN_RIGHT: u32 = 0x111; +const BTN_MIDDLE: u32 = 0x112; +const BTN_FORWARD: u32 = 0x115; +const BTN_BACK: u32 = 0x116; + +pub struct PointerEmulationGrab { + start_data: GrabStartData, + seat: Seat, + + above_source: bool, + tip_down: bool, + button_down: Vec, +} + +impl PointerEmulationGrab { + pub fn new(start_data: GrabStartData, seat: Seat) -> Self { + Self { + start_data, + seat, + + above_source: true, + tip_down: false, + button_down: Vec::new(), + } + } + + fn button_to_mouse(&self, button: u32) -> Option { + // FIXME: This should be configurable. + if button == BTN_STYLUS { + Some(MouseButton::Right) + } else if button == BTN_STYLUS_2 { + Some(MouseButton::Middle) + } else { + None + } + } + + fn pointer_button(&self, data: &mut State, button: MouseButton, state: ButtonState) { + if let Some(pointer) = self.seat.get_pointer() { + let button = match button { + MouseButton::Left => BTN_LEFT, + MouseButton::Right => BTN_RIGHT, + MouseButton::Middle => BTN_MIDDLE, + MouseButton::Back => BTN_BACK, + MouseButton::Forward => BTN_FORWARD, + _ => return, + }; + + pointer.button( + data, + &pointer::ButtonEvent { + serial: SERIAL_COUNTER.next_serial(), + button, + state, + time: InputTime::now(), + }, + ); + + pointer.frame(data); + } + } +} + +type Type = tablet::tool::MotionEvent; + +impl TabletToolGrab for PointerEmulationGrab { + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus.clone(), event); + + if !self.above_source && !self.tip_down && self.button_down.is_empty() { + handle.unset_grab( + self, + data, + SERIAL_COUNTER.next_serial(), + InputTime::now(), + true, + ); + } else if let Some(pointer) = self.seat.get_pointer() { + pointer.motion( + data, + focus, + &pointer::MotionEvent { + location: event.location, + serial: SERIAL_COUNTER.next_serial(), + time: InputTime::now(), + }, + ); + pointer.frame(data); + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.proximity_out(data, event); + + handle.unset_grab(self, data, event.serial, event.time, true); + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &DownEvent, + ) { + handle.down(data, event); + self.tip_down = true; + + self.pointer_button(data, MouseButton::Left, ButtonState::Pressed); + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &UpEvent, + ) { + handle.up(data, event); + + self.pointer_button(data, MouseButton::Left, ButtonState::Released); + self.tip_down = false; + + if !self.above_source && !self.tip_down && self.button_down.is_empty() { + handle.unset_grab(self, data, event.serial, event.time, true); + } + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &Type, + ) { + self.above_source = focus.as_ref().map(|(target, _)| target) + == self.start_data.focus.as_ref().map(|(target, _)| target); + handle.motion(data, self.start_data.focus.clone(), event); + + if !self.above_source && !self.tip_down && self.button_down.is_empty() { + handle.unset_grab( + self, + data, + SERIAL_COUNTER.next_serial(), + InputTime::now(), + true, + ); + } else if let Some(pointer) = self.seat.get_pointer() { + pointer.motion( + data, + focus, + &pointer::MotionEvent { + location: event.location, + serial: SERIAL_COUNTER.next_serial(), + time: InputTime::now(), + }, + ); + pointer.frame(data); + } + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ButtonEvent, + ) { + handle.button(data, event); + + self.button_down.retain(|b| b != &event.button); + if matches!(event.state, ButtonState::Pressed) { + self.button_down.push(event.button); + } + + if let Some(button) = self.button_to_mouse(event.button) { + self.pointer_button(data, button, event.state); + } + + if !self.above_source && !self.tip_down && self.button_down.is_empty() { + handle.unset_grab( + self, + data, + SERIAL_COUNTER.next_serial(), + InputTime::now(), + true, + ); + } + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: AxisFrame, + ) { + handle.axis(data, frame); + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time); + } + + fn unset(&mut self, data: &mut State) { + if self.tip_down { + self.pointer_button(data, MouseButton::Left, ButtonState::Released); + } + + let buttons = std::mem::take(&mut self.button_down); + for button in buttons.into_iter() { + if let Some(button) = self.button_to_mouse(button) { + self.pointer_button(data, button, ButtonState::Released); + } + } + } + + fn start_data(&self) -> &GrabStartData { + &self.start_data + } +} diff --git a/src/libei.rs b/src/libei.rs index ad3a674d..487f0387 100644 --- a/src/libei.rs +++ b/src/libei.rs @@ -124,7 +124,9 @@ pub fn setup_ei( data.update_ei_input_method(); // Notify the remaining libei clients of the now-cleared modifier state let seat = data.common.shell.read().seats.last_active().clone(); - data.broadcast_ei_keyboard_modifiers(&seat); + if let Some(keyboard) = seat.get_keyboard() { + data.broadcast_ei_keyboard_modifiers(&keyboard); + } } EiInputEvent::Event(event) => { use smithay::backend::input::{InputEvent, KeyboardKeyEvent}; diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index 14736719..d4743b7f 100644 --- a/src/shell/element/mod.rs +++ b/src/shell/element/mod.rs @@ -12,7 +12,7 @@ use id_tree::NodeId; use smithay::{ backend::{ drm::DrmNode, - input::KeyState, + input::{InputTime, KeyState}, renderer::{ element::{ Element, Kind, RenderElement, UnderlyingStorage, @@ -1012,7 +1012,7 @@ impl KeyboardTarget for CosmicMapped { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: u32, + time: InputTime, ) { match &self.element { CosmicMappedInternal::Stack(s) => { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 7ce26204..7f7f6317 100644 --- a/src/shell/element/stack.rs +++ b/src/shell/element/stack.rs @@ -11,7 +11,7 @@ use crate::{ shell::{ element::{CosmicMappedKey, CosmicMappedKeyInner}, focus::target::PointerFocusTarget, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabType, ReleaseMode, ResizeEdge}, layout::tiling::NodeDesc, }, state::State, @@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection}; use smithay::{ backend::{ drm::DrmNode, - input::KeyState, + input::{InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -52,14 +52,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, + }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -112,6 +121,7 @@ pub struct CosmicStackInternal { previous_keyboard: AtomicUsize, pointer_entered: AtomicU8, touch_serial: AtomicU32, + tablet_serial: AtomicU32, reenter: AtomicBool, potential_drag: Mutex>, override_alive: AtomicBool, @@ -171,6 +181,7 @@ impl CosmicStack { previous_keyboard: AtomicUsize::new(0), pointer_entered: AtomicU8::new(0), touch_serial: AtomicU32::new(0), + tablet_serial: AtomicU32::new(0), reenter: AtomicBool::new(false), potential_drag: Mutex::new(None), override_alive: AtomicBool::new(true), @@ -831,7 +842,7 @@ impl CosmicStack { ))); }; - let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]); + let radii = radii.map(|[_, _, c, d]| [0, 0, c, d]); windows[active].push_render_elements( renderer, window_loc, @@ -909,12 +920,19 @@ impl CosmicStack { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(state, grab, serial, focus); + .set_grab(state, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } }); @@ -997,17 +1015,17 @@ impl CosmicStack { .corner_radius(geometry_size) .unwrap_or([default_radius; 4]); + corners[0] = 0; corners[1] = 0; - corners[3] = 0; corners } else { let mut corners = active_window.corner_radius(geometry_size).unwrap_or(radii); - corners[0] = radii[0].max(corners[0]); + corners[0] = radii[0]; corners[1] = radii[1]; corners[2] = radii[2].max(corners[2]); - corners[3] = radii[3]; + corners[3] = radii[3].max(corners[3]); corners } @@ -1089,12 +1107,19 @@ impl Program for CosmicStackInternal { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(state, grab, serial, focus); + .set_grab(state, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } }); @@ -1547,7 +1572,7 @@ impl KeyboardTarget for CosmicStack { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: u32, + time: InputTime, ) { let active = self.keyboard_leave_if_previous(seat, data, serial); self.0.with_program(|p| { @@ -1587,7 +1612,7 @@ impl KeyboardTarget for CosmicStack { } impl PointerTarget for CosmicStack { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; @@ -1615,7 +1640,7 @@ impl PointerTarget for CosmicStack { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active = p.active.load(Ordering::SeqCst); @@ -1658,7 +1683,7 @@ impl PointerTarget for CosmicStack { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1689,14 +1714,12 @@ impl PointerTarget for CosmicStack { state.common.config.cosmic_conf.edge_snap_threshold, false, ); - if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus); - } + if let Some((grab, focus)) = res + && let GrabType::Pointer = grab.grab_type() + { + seat.get_pointer() + .unwrap() + .set_grab(state, grab, serial, focus); } }); } @@ -1704,7 +1727,7 @@ impl PointerTarget for CosmicStack { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1716,7 +1739,7 @@ impl PointerTarget for CosmicStack { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { self.0.with_program(|p| { let mut cursor_state = seat .user_data() @@ -1752,14 +1775,12 @@ impl PointerTarget for CosmicStack { &state.common.event_loop_handle, false, ); - if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus); - } + if let Some((grab, focus)) = res + && let GrabType::Pointer = grab.grab_type() + { + seat.get_pointer() + .unwrap() + .set_grab(state, grab, serial, focus); } }); } @@ -1832,7 +1853,7 @@ impl PointerTarget for CosmicStack { } impl TouchTarget for CosmicStack { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let mut event = event.clone(); let active_window_geo = self.0.with_program(|p| { p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() @@ -1843,7 +1864,7 @@ impl TouchTarget for CosmicStack { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1891,6 +1912,185 @@ impl TouchTarget for CosmicStack { } } +impl TabletToolTarget for CosmicStack { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial) + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + self.0.with_program(|p| { + let mut cursor_state = seat + .user_data() + .get::() + .unwrap() + .lock() + .unwrap(); + cursor_state.unset_shape(); + let _previous = p.swap_focus(None); + }); + TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor); + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + self.0.with_program(|p| { + p.tablet_serial + .store(event.serial.into(), Ordering::Release) + }); + match self.0.with_program(|p| p.current_focus()) { + Some(Focus::Header) => { + TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event) + } + Some(x) => { + let serial = self + .0 + .with_program(|p| p.tablet_serial.load(Ordering::Acquire)) + .into(); + let seat = seat.clone(); + let Some(surface) = self.0.with_program(|p| { + let window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; + window.wl_surface().map(Cow::into_owned) + }) else { + return; + }; + self.0.loop_handle().insert_idle(move |state| { + let res = state.common.shell.write().resize_request( + &surface, + &seat, + serial, + match x { + Focus::ResizeTop => ResizeEdge::TOP, + Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT, + Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT, + Focus::ResizeBottom => ResizeEdge::BOTTOM, + Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT, + Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT, + Focus::ResizeLeft => ResizeEdge::LEFT, + Focus::ResizeRight => ResizeEdge::RIGHT, + Focus::Header => unreachable!(), + }, + state.common.config.cosmic_conf.edge_snap_threshold, + false, + ); + if let Some((grab, focus)) = res + && let GrabType::TabletTool = grab.grab_type() + { + seat.tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus); + } + }); + } + None => {} + } + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event) + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + let mut event = event.clone(); + self.0.with_program(|p| { + let active = p.active.load(Ordering::SeqCst); + let active_window = &p.windows.lock().unwrap()[active]; + let Some(next) = Focus::under(active_window, TAB_HEIGHT, event.location) else { + return; + }; + let _previous = p.swap_focus(Some(next)); + + let mut cursor_state = seat + .user_data() + .get::() + .unwrap() + .lock() + .unwrap(); + cursor_state.set_shape(next.cursor_shape()); + seat.set_cursor_image_status(CursorImageStatus::default_named()); + }); + + let active_window_geo = self.0.with_program(|p| { + p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() + }); + event.location -= active_window_geo.loc.to_f64(); + + TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event); + if event.location.y < 0.0 + || event.location.y > TAB_HEIGHT as f64 + || event.location.x < 64.0 + || event.location.x > (active_window_geo.size.w as f64 - 64.0) + { + self.start_drag( + data, + seat, + self.0 + .with_program(|p| p.tablet_serial.load(Ordering::Acquire)) + .into(), + ); + } + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame) + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event) + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time) + } +} + pub enum CosmicStackRenderElement { Header(IcedRenderElement), Shadow(PixelShaderElement), diff --git a/src/shell/element/stack/tab.rs b/src/shell/element/stack/tab.rs index 1a311dfc..5613f76e 100644 --- a/src/shell/element/stack/tab.rs +++ b/src/shell/element/stack/tab.rs @@ -8,6 +8,7 @@ use cosmic::{ layout::{Layout, Limits, Node}, mouse, overlay, renderer, text::{Ellipsize, EllipsizeHeightLimit, Shaping, Wrapping}, + touch, widget::{Id, Widget, operation::Operation, tree::Tree}, }, widget::{self, container::draw_background, rule::FillMode, scrollable::AbsoluteOffset}, @@ -370,6 +371,7 @@ where if matches!( event, event::Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) + | event::Event::Touch(touch::Event::FingerPressed { .. }) ) && let Some(message) = self.press_message.clone() { shell.publish(message); @@ -388,6 +390,7 @@ where if matches!( event, event::Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) + | event::Event::Touch(touch::Event::FingerLifted { .. }) ) { shell.publish(Message::activate(self.idx)); shell.capture_event(); diff --git a/src/shell/element/stack/tabs.rs b/src/shell/element/stack/tabs.rs index 86218db6..9dd5ef81 100644 --- a/src/shell/element/stack/tabs.rs +++ b/src/shell/element/stack/tabs.rs @@ -31,7 +31,7 @@ use keyframe::{ functions::{EaseInOutCubic, EaseOutCubic}, }; use std::{ - collections::{HashMap, HashSet, VecDeque}, + collections::{HashMap, VecDeque}, time::{Duration, Instant}, }; @@ -757,12 +757,10 @@ where state.last_state = Some(current_state.clone()); } let last_state = state.last_state.as_mut().unwrap(); - let unknown_keys = current_state - .keys() - .collect::>() - .symmetric_difference(&last_state.keys().collect::>()) - .next() - .is_some(); + let unknown_keys = current_state.len() != last_state.len() + || current_state + .keys() + .any(|key| !last_state.contains_key(key)); enum Difference { NewOrRemoved, diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index 99bb2f78..a7fd922d 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -21,6 +21,7 @@ use std::{ use smithay::{ backend::{ drm::DrmNode, + input::InputTime, renderer::{ ImportAll, Renderer, buffer_has_alpha, element::{Kind, RenderElementStates, surface::KindEvaluation}, @@ -1084,7 +1085,7 @@ impl KeyboardTarget for CosmicSurface { key: KeysymHandle<'_>, state: smithay::backend::input::KeyState, serial: smithay::utils::Serial, - time: u32, + time: InputTime, ) { match self.0.underlying_surface() { WindowSurface::Wayland(toplevel) => { diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index 838efd24..c06609fe 100644 --- a/src/shell/element/window.rs +++ b/src/shell/element/window.rs @@ -7,7 +7,7 @@ use crate::{ shell::{ element::{CosmicMappedKey, CosmicMappedKeyInner}, focus::target::PointerFocusTarget, - grabs::{ReleaseMode, ResizeEdge}, + grabs::{GrabType, ReleaseMode, ResizeEdge}, }, state::State, utils::{ @@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig; use smithay::{ backend::{ drm::DrmNode, - input::KeyState, + input::{InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -35,14 +35,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent, - GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, - GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, - GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, + CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -429,12 +438,12 @@ impl CosmicWindow { .map(|x| (x * scale as f32).round() as u8); if has_ssd && !clip { // bottom corners - radii[0] = 0; radii[2] = 0; + radii[3] = 0; if is_tiled { // top corners + radii[0] = 0; radii[1] = 0; - radii[3] = 0; } } @@ -501,12 +510,12 @@ impl CosmicWindow { && !is_maximized; if has_ssd && !clip { // bottom corners - radii[0] = 0; radii[2] = 0; + radii[3] = 0; if is_tiled { // top corners + radii[0] = 0; radii[1] = 0; - radii[3] = 0; } } @@ -551,8 +560,8 @@ impl CosmicWindow { self.0.with_program(|p| { let mut radii = radii; if has_ssd { + radii[0] = 0; radii[1] = 0; - radii[3] = 0; } let theme = p.theme.lock().unwrap(); let frosted = if theme.cosmic().frosted_windows { @@ -576,8 +585,8 @@ impl CosmicWindow { }); if has_ssd { - radii[0] = 0; radii[2] = 0; + radii[3] = 0; let ssd_loc = location + self .0 @@ -682,26 +691,26 @@ impl CosmicWindow { (has_ssd, true) => { let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii); - corners[0] = radii[0].max(corners[0]); + corners[0] = if has_ssd { + radii[0] + } else { + radii[0].max(corners[0]) + }; corners[1] = if has_ssd { radii[1] } else { radii[1].max(corners[1]) }; corners[2] = radii[2].max(corners[2]); - corners[3] = if has_ssd { - radii[3] - } else { - radii[3].max(corners[3]) - }; + corners[3] = radii[3].max(corners[3]); corners } (true, false) => p .window .corner_radius(geometry_size) - .map(|[a, _, c, _]| [a, radii[1], c, radii[3]]) - .unwrap_or([default_radius, radii[1], default_radius, radii[3]]), + .map(|[_, _, c, d]| [radii[0], radii[1], c, d]) + .unwrap_or([radii[0], radii[1], default_radius, default_radius]), (false, false) => p .window .corner_radius(geometry_size) @@ -746,12 +755,19 @@ impl Program for CosmicWindowInternal { false, ); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(state, grab, serial, focus); + .set_grab(state, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } }); @@ -981,7 +997,7 @@ impl KeyboardTarget for CosmicWindow { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: u32, + time: InputTime, ) { self.0 .with_program(|p| KeyboardTarget::key(&p.window, seat, data, key, state, serial, time)) @@ -999,7 +1015,7 @@ impl KeyboardTarget for CosmicWindow { } impl PointerTarget for CosmicWindow { - fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1012,8 +1028,7 @@ impl PointerTarget for CosmicWindow { return; }; - let old_focus = p.swap_focus(Some(next)); - assert_eq!(old_focus, None); + let _ = p.swap_focus(Some(next)); let cursor_state = seat.user_data().get::().unwrap(); cursor_state.lock().unwrap().set_shape(next.cursor_shape()); @@ -1025,7 +1040,7 @@ impl PointerTarget for CosmicWindow { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1057,7 +1072,7 @@ impl PointerTarget for CosmicWindow { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1093,14 +1108,12 @@ impl PointerTarget for CosmicWindow { false, ); - if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus); - } + if let Some((grab, focus)) = res + && let GrabType::Pointer = grab.grab_type() + { + seat.get_pointer() + .unwrap() + .set_grab(state, grab, serial, focus) } }); } @@ -1108,7 +1121,7 @@ impl PointerTarget for CosmicWindow { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1120,7 +1133,7 @@ impl PointerTarget for CosmicWindow { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { self.0.with_program(|p| { let cursor_state = seat.user_data().get::().unwrap(); cursor_state.lock().unwrap().unset_shape(); @@ -1195,7 +1208,7 @@ impl PointerTarget for CosmicWindow { } impl TouchTarget for CosmicWindow { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let mut event = event.clone(); self.0.with_program(|p| { event.location -= p.window.geometry().loc.to_f64(); @@ -1203,7 +1216,7 @@ impl TouchTarget for CosmicWindow { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1234,6 +1247,155 @@ impl TouchTarget for CosmicWindow { } } +impl TabletToolTarget for CosmicWindow { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + TabletToolTarget::proximity_in(&self.0, seat, data, tool_descriptor, tablet, serial) + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + self.0.with_program(|p| { + let cursor_state = seat.user_data().get::().unwrap(); + cursor_state.lock().unwrap().unset_shape(); + let _previous = p.swap_focus(None); + }); + TabletToolTarget::proximity_out(&self.0, seat, data, tool_descriptor) + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + match self.0.with_program(|p| p.current_focus()) { + Some(Focus::Header) => { + TabletToolTarget::down(&self.0, seat, data, tool_descriptor, event) + } + Some(x) => { + let serial = event.serial; + let seat = seat.clone(); + let Some(surface) = self.wl_surface().map(Cow::into_owned) else { + return; + }; + + self.0.loop_handle().insert_idle(move |state| { + let res = state.common.shell.write().resize_request( + &surface, + &seat, + serial, + match x { + Focus::ResizeTop => ResizeEdge::TOP, + Focus::ResizeTopLeft => ResizeEdge::TOP_LEFT, + Focus::ResizeTopRight => ResizeEdge::TOP_RIGHT, + Focus::ResizeBottom => ResizeEdge::BOTTOM, + Focus::ResizeBottomLeft => ResizeEdge::BOTTOM_LEFT, + Focus::ResizeBottomRight => ResizeEdge::BOTTOM_RIGHT, + Focus::ResizeLeft => ResizeEdge::LEFT, + Focus::ResizeRight => ResizeEdge::RIGHT, + Focus::Header => unreachable!(), + }, + state.common.config.cosmic_conf.edge_snap_threshold, + false, + ); + + if let Some((grab, focus)) = res + && let GrabType::TabletTool = grab.grab_type() + { + seat.tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus) + } + }); + } + None => {} + } + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + TabletToolTarget::up(&self.0, seat, data, tool_descriptor, event) + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + let mut event = event.clone(); + self.0.with_program(|p| { + let has_ssd = p.has_ssd(false); + if has_ssd || p.has_tiled_state() { + let Some(next) = Focus::under( + &p.window, + if has_ssd { SSD_HEIGHT } else { 0 }, + event.location, + ) else { + return; + }; + let _previous = p.swap_focus(Some(next)); + + let cursor_state = seat.user_data().get::().unwrap(); + cursor_state.lock().unwrap().set_shape(next.cursor_shape()); + seat.set_cursor_image_status(CursorImageStatus::default_named()); + } + }); + + event.location -= self.0.with_program(|p| p.window.geometry().loc.to_f64()); + TabletToolTarget::motion(&self.0, seat, data, tool_descriptor, &event) + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + TabletToolTarget::axis(&self.0, seat, data, tool_descriptor, frame) + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + TabletToolTarget::button(&self.0, seat, data, tool_descriptor, event) + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + TabletToolTarget::frame(&self.0, seat, data, tool_descriptor, time) + } +} + impl WaylandFocus for CosmicWindow { fn wl_surface(&self) -> Option> { self.0.with_program(|p| { diff --git a/src/shell/focus/mod.rs b/src/shell/focus/mod.rs index cab37a85..f631372e 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -6,6 +6,7 @@ use crate::{ }; use indexmap::IndexSet; use smithay::{ + backend::input::InputTime, desktop::{PopupUngrabStrategy, layer_map_for_output}, input::{Seat, pointer::MotionEvent}, output::Output, @@ -419,7 +420,7 @@ fn update_focus_state( &MotionEvent { location: new_pos.as_logical(), serial: SERIAL_COUNTER.next_serial(), - time: 0, + time: InputTime::now(), }, ); } @@ -768,7 +769,7 @@ fn update_pointer_focus(state: &mut State, seat: &Seat) { &MotionEvent { location: pointer.current_location(), serial: SERIAL_COUNTER.next_serial(), - time: state.common.clock.now().as_millis(), + time: InputTime::now(), }, ); } diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index 80b1a34f..c914e0fa 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -16,21 +16,30 @@ use crate::{ }; use id_tree::NodeId; use smithay::{ - backend::input::KeyState, + backend::input::{InputTime, KeyState, TabletToolDescriptor}, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, input::{ Seat, dnd::{DndFocus, OfferData, Source}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolHandle, + TabletToolTarget, UpEvent as ToolUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, reexports::wayland_server::{ @@ -164,6 +173,17 @@ impl PointerFocusTarget { } } + fn inner_tablet_tool_target(&self) -> &dyn TabletToolTarget { + match self { + PointerFocusTarget::WlSurface { surface, .. } => surface, + PointerFocusTarget::X11Surface { surface, .. } => surface, + PointerFocusTarget::StackUI(u) => u, + PointerFocusTarget::WindowUI(u) => u, + PointerFocusTarget::ResizeFork(f) => f, + PointerFocusTarget::ZoomUI(e) => e, + } + } + pub fn under_surface>>( surface: &CosmicSurface, point: P, @@ -272,9 +292,10 @@ impl PointerFocusTarget { None }; - let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) = - seat.cursor_geometry((0.0, 0.0), Duration::from_millis(event.time as u64).into()) - { + let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) = seat.cursor_geometry( + (0.0, 0.0), + Duration::from_millis(event.time.millis() as u64).into(), + ) { hotspot } else { Point::from((0, 0)) @@ -285,6 +306,16 @@ impl PointerFocusTarget { session.set_cursor_hotspot(cursor_hotspot); } } + + pub fn supports_tool(&self, tool_handle: &TabletToolHandle) -> bool { + match self { + Self::WlSurface { surface, .. } if surface.client().is_some() => tool_handle + .client_tools(&surface.client().unwrap()) + .next() + .is_some(), + _ => true, + } + } } impl KeyboardFocusTarget { @@ -408,16 +439,16 @@ impl PointerTarget for PointerFocusTarget { self.inner_pointer_target() .relative_motion(seat, data, event); } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { self.inner_pointer_target().button(seat, data, event); } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { self.inner_pointer_target().axis(seat, data, frame); } fn frame(&self, seat: &Seat, data: &mut State) { self.inner_pointer_target().frame(seat, data); } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { let toplevel = self.toplevel(&data.common.shell.read()); if let Some(element) = toplevel { for session in element.cursor_sessions() { @@ -497,12 +528,102 @@ impl PointerTarget for PointerFocusTarget { } } +impl TabletToolTarget for PointerFocusTarget { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + self.inner_tablet_tool_target() + .proximity_in(seat, data, tool_descriptor, tablet, serial); + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + self.inner_tablet_tool_target() + .proximity_out(seat, data, tool_descriptor); + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + self.inner_tablet_tool_target() + .down(seat, data, tool_descriptor, event); + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolUpEvent, + ) { + self.inner_tablet_tool_target() + .up(seat, data, tool_descriptor, event); + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + self.inner_tablet_tool_target() + .motion(seat, data, tool_descriptor, event); + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: ToolAxisFrame, + ) { + self.inner_tablet_tool_target() + .axis(seat, data, tool_descriptor, frame); + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + self.inner_tablet_tool_target() + .button(seat, data, tool_descriptor, event); + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + self.inner_tablet_tool_target() + .frame(seat, data, tool_descriptor, time); + } +} + impl TouchTarget for PointerFocusTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { self.inner_touch_target().down(seat, data, event); } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { self.inner_touch_target().up(seat, data, event); } @@ -593,7 +714,7 @@ impl DndFocus for PointerFocusTarget { offer: Option<&mut CosmicOfferData>, seat: &Seat, location: Point, - time: u32, + time: InputTime, ) { match self { PointerFocusTarget::WlSurface { surface, .. } => { @@ -695,7 +816,7 @@ impl KeyboardTarget for KeyboardFocusTarget { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: u32, + time: InputTime, ) { if let Some(inner) = self.inner_keyboard_target() { inner.key(seat, data, key, state, serial, time); diff --git a/src/shell/grabs/delay.rs b/src/shell/grabs/delay.rs index 96d33dc6..ca19e4cb 100644 --- a/src/shell/grabs/delay.rs +++ b/src/shell/grabs/delay.rs @@ -1,22 +1,34 @@ use smithay::{ + backend::input::{InputTime, TabletToolDescriptor}, input::{ Seat, SeatHandler, pointer::{ - AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab, - PointerInnerHandle, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, + RelativeMotionEvent, + }, + tablet::{ + TabletSeatHandler, TabletSeatTrait, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData, + MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent, + TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, + DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, + MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, + TouchInnerHandle, UpEvent as TouchUpEvent, }, }, utils::{Logical, Point, SERIAL_COUNTER, Serial}, }; -use crate::state::State; +use crate::{shell::grabs::GrabType, state::State}; use super::GrabStartData; @@ -44,10 +56,15 @@ impl DelayGrab { } } - pub fn is_touch_grab(&self) -> bool { - match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + pub fn grab_type(&self) -> GrabType { + self.start_data.type_() + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -92,7 +109,7 @@ impl> PointerGrab for DelayGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(data, event); if handle.current_pressed().is_empty() { @@ -104,7 +121,7 @@ impl> PointerGrab for DelayGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details); } @@ -201,12 +218,17 @@ impl> TouchGrab for DelayGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(::TouchFocus, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { handle.down(data, focus, event); } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { handle.up(data, event); if event.slot == TouchGrab::start_data(self).slot { @@ -273,3 +295,110 @@ impl> TouchGrab for DelayGrab { fn unset(&mut self, _data: &mut State) {} } + +impl> TabletToolGrab for DelayGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.proximity_out(data, event); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + handle.motion(data, focus, event); + + let distance = self.start_data.distance(event.location); + if distance >= 1. + && let Some(factory) = self.grab_factory.take() + { + let seat = self.seat.clone(); + let serial = self.serial.unwrap_or_else(|| SERIAL_COUNTER.next_serial()); + let time = InputTime::now(); + let Some(tool) = self.tool().cloned() else { + handle.unset_grab(self, data, serial, time, true); + return; + }; + data.common.event_loop_handle.insert_idle(move |data| { + if let Some((grab, focus)) = factory(data) { + seat.tablet_seat() + .get_tool(&tool) + .unwrap() + .set_grab(data, grab, time, serial, focus); + } + }); + } + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + handle.down(data, event) + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + handle.up(data, event); + handle.unset_grab(self, data, event.serial, event.time, false); + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + handle.button(data, event); + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: TabletAxisFrame, + ) { + handle.axis(data, frame) + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time) + } + + fn unset(&mut self, _data: &mut State) {} + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus, event); + } +} diff --git a/src/shell/grabs/menu/default.rs b/src/shell/grabs/menu/default.rs index c7418b6d..26cca2f5 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -1,7 +1,10 @@ use cosmic_settings_config::shortcuts::Action; use smithay::{ - input::pointer::MotionEvent, reexports::wayland_server::protocol::wl_surface::WlSurface, - utils::SERIAL_COUNTER, wayland::seat::WaylandFocus, + backend::input::InputTime, + input::{pointer::MotionEvent, tablet::TabletSeatTrait}, + reexports::wayland_server::protocol::wl_surface::WlSurface, + utils::SERIAL_COUNTER, + wayland::seat::WaylandFocus, }; use crate::{ @@ -10,7 +13,7 @@ use crate::{ shell::{ CosmicSurface, PointGlobalExt, Shell, element::{CosmicMapped, CosmicWindow}, - grabs::ReleaseMode, + grabs::{GrabType, ReleaseMode}, }, state::State, utils::{prelude::SeatExt, screenshot::screenshot_window}, @@ -352,19 +355,20 @@ pub fn window_items( std::mem::drop(shell); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab( - state, - grab, - SERIAL_COUNTER.next_serial(), - ) - } else { - seat.get_pointer().unwrap().set_grab( - state, - grab, - SERIAL_COUNTER.next_serial(), - focus, - ); + let serial = SERIAL_COUNTER.next_serial(); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat + .get_pointer() + .unwrap() + .set_grab(state, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } } @@ -388,21 +392,29 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - let pointer = seat.get_pointer().unwrap(); - pointer.motion( - state, - target, - &MotionEvent { - location: loc.as_logical().to_f64(), - serial, - time: state.common.clock.now().as_millis(), - }, - ); - pointer.frame(state); - pointer.set_grab(state, grab, serial, focus); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), + GrabType::Pointer => { + let pointer = seat.get_pointer().unwrap(); + pointer.motion( + state, + target, + &MotionEvent { + location: loc.as_logical().to_f64(), + serial, + time: InputTime::now(), + }, + ); + pointer.frame(state); + pointer.set_grab(state, grab, serial, focus); + } } } }); @@ -423,21 +435,30 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - let pointer = seat.get_pointer().unwrap(); - pointer.motion( - state, - target, - &MotionEvent { - location: loc.as_logical().to_f64(), - serial, - time: state.common.clock.now().as_millis(), - }, - ); - pointer.frame(state); - pointer.set_grab(state, grab, serial, focus); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => { + let pointer = seat.get_pointer().unwrap(); + pointer.motion( + state, + target, + &MotionEvent { + location: loc.as_logical().to_f64(), + serial, + time: InputTime::now(), + }, + ); + pointer.frame(state); + pointer.set_grab(state, grab, serial, focus); + } + GrabType::TabletTool => { + seat.tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus); + } } } }); @@ -458,21 +479,30 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - let pointer = seat.get_pointer().unwrap(); - pointer.motion( - state, - target, - &MotionEvent { - location: loc.as_logical().to_f64(), - serial, - time: state.common.clock.now().as_millis(), - }, - ); - pointer.frame(state); - pointer.set_grab(state, grab, serial, focus); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => { + let pointer = seat.get_pointer().unwrap(); + pointer.motion( + state, + target, + &MotionEvent { + location: loc.as_logical().to_f64(), + serial, + time: InputTime::now(), + }, + ); + pointer.frame(state); + pointer.set_grab(state, grab, serial, focus); + } + GrabType::TabletTool => { + seat.tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus); + } } } }); @@ -493,21 +523,29 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - let pointer = seat.get_pointer().unwrap(); - pointer.motion( - state, - target, - &MotionEvent { - location: loc.as_logical().to_f64(), - serial, - time: state.common.clock.now().as_millis(), - }, - ); - pointer.frame(state); - pointer.set_grab(state, grab, serial, focus); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => { + let pointer = seat.get_pointer().unwrap(); + pointer.motion( + state, + target, + &MotionEvent { + location: loc.as_logical().to_f64(), + serial, + time: InputTime::now(), + }, + ); + pointer.frame(state); + pointer.set_grab(state, grab, serial, focus); + } + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } }); @@ -627,19 +665,20 @@ pub fn fullscreen_items(window: &CosmicSurface, config: &Config) -> impl Iterato std::mem::drop(shell); if let Some((grab, focus)) = res { - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab( - state, - grab, - SERIAL_COUNTER.next_serial(), - ) - } else { - seat.get_pointer().unwrap().set_grab( - state, - grab, - SERIAL_COUNTER.next_serial(), - focus, - ); + let serial = SERIAL_COUNTER.next_serial(); + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat + .get_pointer() + .unwrap() + .set_grab(state, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(state, grab, InputTime::now(), serial, focus), } } } diff --git a/src/shell/grabs/menu/mod.rs b/src/shell/grabs/menu/mod.rs index 1eb571f1..9ea37a31 100644 --- a/src/shell/grabs/menu/mod.rs +++ b/src/shell/grabs/menu/mod.rs @@ -19,22 +19,33 @@ use cosmic::{ }; use smithay::{ backend::{ - input::{ButtonState, TouchSlot}, + input::{ButtonState, InputTime, TabletToolDescriptor, TouchSlot}, renderer::ImportMem, }, desktop::space::SpaceElement, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab, - PointerInnerHandle, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget, + RelativeMotionEvent, + }, + tablet::{ + TabletSeatHandler, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData, + MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent, + TabletToolGrab, TabletToolInnerHandle, TabletToolTarget, UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, - TouchGrab, TouchInnerHandle, TouchTarget, UpEvent, + DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, + MotionEvent as TouchMotionEvent, TouchGrab, TouchInnerHandle, TouchTarget, + UpEvent as TouchUpEvent, }, }, output::Output, @@ -43,7 +54,7 @@ use smithay::{ use crate::{ backend::render::element::AsGlowRenderer, - shell::{SeatExt, focus::target::PointerFocusTarget}, + shell::{SeatExt, focus::target::PointerFocusTarget, grabs::GrabType}, state::State, utils::{ iced::{IcedElement, IcedRenderElement, Program}, @@ -350,6 +361,7 @@ impl Program for ContextMenu { position, pointer_entered: false, touch_entered: None, + tablet_entered: None, }) } }); @@ -509,6 +521,7 @@ pub struct Element { position: Point, pointer_entered: bool, touch_entered: Option, + tablet_entered: Option, } pub struct MenuGrab { @@ -517,6 +530,7 @@ pub struct MenuGrab { seat: Seat, screen_space_relative: Option, scale: Arc>, + last_tablet_idx: Option, } impl PointerGrab for MenuGrab { @@ -599,7 +613,7 @@ impl PointerGrab for MenuGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { let any_entered = self .elements @@ -633,7 +647,7 @@ impl PointerGrab for MenuGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(state, details); } @@ -730,7 +744,7 @@ impl TouchGrab for MenuGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { { let mut guard = self.elements.lock().unwrap(); @@ -758,7 +772,7 @@ impl TouchGrab for MenuGrab { }) { let element = &mut elements[i]; - let new_event = DownEvent { + let new_event = TouchDownEvent { slot: event.slot, location: event_location - element.position.as_logical().to_f64(), serial: event.serial, @@ -773,7 +787,12 @@ impl TouchGrab for MenuGrab { handle.down(data, None, event); } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { { let elements = self.elements.lock().unwrap(); for element in elements.iter().filter(|elem| { @@ -849,6 +868,248 @@ impl TouchGrab for MenuGrab { fn unset(&mut self, _data: &mut State) {} } +impl TabletToolGrab for MenuGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + { + let location = if let Some(output) = self.screen_space_relative.as_ref() { + if data.common.shell.read().zoom_state().is_some() { + event + .location + .as_global() + .to_zoomed(output) + .to_global(output) + .as_logical() + } else { + event.location + } + } else { + event.location + }; + + let mut elements = self.elements.lock().unwrap(); + if let Some(i) = elements.iter().position(|elem| { + let mut bbox = elem.iced.bbox(); + bbox.loc = elem.position.as_logical(); + + bbox.contains(location.to_i32_floor()) + }) { + let element = &mut elements[i]; + + let new_event = TabletMotionEvent { + location: location - element.position.as_logical().to_f64(), + serial: event.serial, + time: event.time, + }; + + TabletToolTarget::proximity_in( + &element.iced, + &self.seat, + data, + handle.descriptor(), + &handle.current_tablet(), + event.serial, + ); + element.tablet_entered = Some(handle.descriptor().clone()); + TabletToolTarget::motion( + &element.iced, + &self.seat, + data, + handle.descriptor(), + &new_event, + ); + self.last_tablet_idx = Some(i); + } + } + handle.proximity_in(data, None, event); + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + { + let mut elements = self.elements.lock().unwrap(); + for element in elements.iter_mut().filter(|elem| { + elem.tablet_entered + .as_ref() + .is_some_and(|tool| tool == handle.descriptor()) + }) { + TabletToolTarget::proximity_out( + &element.iced, + &self.seat, + data, + handle.descriptor(), + ); + element.tablet_entered.take(); + } + self.last_tablet_idx.take(); + } + handle.unset_grab(self, data, event.serial, event.time, true); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + { + let location = if let Some(output) = self.screen_space_relative.as_ref() { + if data.common.shell.read().zoom_state().is_some() { + event + .location + .as_global() + .to_zoomed(output) + .to_global(output) + .as_logical() + } else { + event.location + } + } else { + event.location + }; + + let mut elements = self.elements.lock().unwrap(); + if let Some(i) = elements.iter().position(|elem| { + let mut bbox = elem.iced.bbox(); + bbox.loc = elem.position.as_logical(); + + bbox.contains(location.to_i32_floor()) + }) { + let element = &mut elements[i]; + + let new_event = TabletMotionEvent { + location: location - element.position.as_logical().to_f64(), + serial: event.serial, + time: event.time, + }; + + if element.tablet_entered.is_none() { + TabletToolTarget::proximity_in( + &element.iced, + &self.seat, + data, + handle.descriptor(), + &handle.current_tablet(), + event.serial, + ); + element.tablet_entered = Some(handle.descriptor().clone()); + } + TabletToolTarget::motion( + &element.iced, + &self.seat, + data, + handle.descriptor(), + &new_event, + ); + self.last_tablet_idx = Some(i); + } else { + elements + .iter_mut() + .filter(|element| element.tablet_entered.is_some()) + .skip(1) + .for_each(|element| { + TabletToolTarget::proximity_out( + &element.iced, + &self.seat, + data, + handle.descriptor(), + ); + }); + self.last_tablet_idx.take(); + } + } + handle.motion(data, None, event); + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + let mut guard = self.elements.lock().unwrap(); + let elements = &mut *guard; + + if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i)) + && elem + .tablet_entered + .as_ref() + .is_some_and(|desc| desc == handle.descriptor()) + { + TabletToolTarget::down(&elem.iced, &self.seat, data, handle.descriptor(), event); + } else { + handle.down(data, event); + } + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + let mut guard = self.elements.lock().unwrap(); + let elements = &mut *guard; + + if let Some(elem) = self.last_tablet_idx.and_then(|i| elements.get_mut(i)) + && elem + .tablet_entered + .as_ref() + .is_some_and(|desc| desc == handle.descriptor()) + { + TabletToolTarget::up(&elem.iced, &self.seat, data, handle.descriptor(), event); + } else { + handle.up(data, event); + } + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + handle.button(data, event); + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: TabletAxisFrame, + ) { + handle.axis(data, frame); + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time); + } + + fn unset(&mut self, _data: &mut State) {} +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct MenuAlignment { pub x: AxisAlignment, @@ -1052,6 +1313,7 @@ impl MenuGrab { position, pointer_entered: false, touch_entered: None, + tablet_entered: None, }])); let scale = Arc::new(Mutex::new(screen_space_relative.unwrap_or(1.))); @@ -1076,6 +1338,7 @@ impl MenuGrab { seat: seat.clone(), screen_space_relative, scale, + last_tablet_idx: None, } } @@ -1086,10 +1349,15 @@ impl MenuGrab { } } - pub fn is_touch_grab(&self) -> bool { - match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + pub fn grab_type(&self) -> GrabType { + self.start_data.type_() + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } diff --git a/src/shell/grabs/mod.rs b/src/shell/grabs/mod.rs index 515916fd..9524f425 100644 --- a/src/shell/grabs/mod.rs +++ b/src/shell/grabs/mod.rs @@ -1,18 +1,26 @@ use calloop::LoopHandle; use cosmic_settings_config::shortcuts; use smithay::{ + backend::input::{InputTime, TabletToolDescriptor}, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, - RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, + }, + tablet::tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData, + MotionEvent as TabletMotionEvent, ProximityOutEvent, TabletToolGrab, + TabletToolInnerHandle, UpEvent as TabletUpEvent, }, touch::{ - DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, + DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, + MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, + TouchInnerHandle, UpEvent as TouchUpEvent, }, }, output::Output, @@ -39,6 +47,17 @@ use super::{ pub enum GrabStartData { Touch(TouchGrabStartData), Pointer(PointerGrabStartData), + TabletTool { + tool: TabletToolDescriptor, + data: TabletGrabStartData, + }, +} + +#[derive(Debug, Clone)] +pub enum GrabType { + Touch, + Pointer, + TabletTool, } impl GrabStartData { @@ -46,6 +65,7 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.focus.as_ref(), Self::Pointer(pointer) => pointer.focus.as_ref(), + Self::TabletTool { data, .. } => data.focus.as_ref(), } } @@ -53,6 +73,7 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.focus = focus, Self::Pointer(pointer) => pointer.focus = focus, + Self::TabletTool { data, .. } => data.focus = focus, } } @@ -60,6 +81,7 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.location, Self::Pointer(pointer) => pointer.location, + Self::TabletTool { data, .. } => data.location, } } @@ -67,6 +89,7 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.location = location, Self::Pointer(pointer) => pointer.location = location, + Self::TabletTool { data, .. } => data.location = location, } } @@ -76,6 +99,14 @@ impl GrabStartData { ((new.x - old.x).powi(2) + (new.y - old.y).powi(2)).sqrt() } + + pub fn type_(&self) -> GrabType { + match self { + Self::Pointer(_) => GrabType::Pointer, + Self::Touch(_) => GrabType::Touch, + Self::TabletTool { .. } => GrabType::TabletTool, + } + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -203,10 +234,17 @@ impl From for ResizeGrab { } impl ResizeGrab { - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self { - ResizeGrab::Floating(grab) => grab.is_touch_grab(), - ResizeGrab::Tiling(grab) => grab.is_touch_grab(), + ResizeGrab::Floating(grab) => grab.grab_type(), + ResizeGrab::Tiling(grab) => grab.grab_type(), + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + match self { + ResizeGrab::Floating(grab) => grab.tool(), + ResizeGrab::Tiling(grab) => grab.tool(), } } } @@ -242,11 +280,11 @@ impl PointerGrab for ResizeGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { match self { - ResizeGrab::Floating(grab) => grab.button(data, handle, event), - ResizeGrab::Tiling(grab) => grab.button(data, handle, event), + ResizeGrab::Floating(grab) => PointerGrab::button(grab, data, handle, event), + ResizeGrab::Tiling(grab) => PointerGrab::button(grab, data, handle, event), } } @@ -254,11 +292,11 @@ impl PointerGrab for ResizeGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { match self { - ResizeGrab::Floating(grab) => grab.axis(data, handle, details), - ResizeGrab::Tiling(grab) => grab.axis(data, handle, details), + ResizeGrab::Floating(grab) => PointerGrab::axis(grab, data, handle, details), + ResizeGrab::Tiling(grab) => PointerGrab::axis(grab, data, handle, details), } } @@ -386,7 +424,7 @@ impl TouchGrab for ResizeGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { match self { ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -394,7 +432,12 @@ impl TouchGrab for ResizeGrab { } } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { match self { ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event), ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event), @@ -467,6 +510,107 @@ impl TouchGrab for ResizeGrab { } } +impl TabletToolGrab for ResizeGrab { + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::down(grab, data, handle, event), + ResizeGrab::Tiling(grab) => TabletToolGrab::down(grab, data, handle, event), + } + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::up(grab, data, handle, event), + ResizeGrab::Tiling(grab) => TabletToolGrab::up(grab, data, handle, event), + } + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &TabletMotionEvent, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::motion(grab, data, handle, focus, event), + ResizeGrab::Tiling(grab) => TabletToolGrab::motion(grab, data, handle, focus, event), + } + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + serial: InputTime, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::frame(grab, data, handle, serial), + ResizeGrab::Tiling(grab) => TabletToolGrab::frame(grab, data, handle, serial), + } + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::button(grab, data, handle, event), + ResizeGrab::Tiling(grab) => TabletToolGrab::button(grab, data, handle, event), + } + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + details: TabletAxisFrame, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::axis(grab, data, handle, details), + ResizeGrab::Tiling(grab) => TabletToolGrab::axis(grab, data, handle, details), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::proximity_out(grab, data, handle, event), + ResizeGrab::Tiling(grab) => TabletToolGrab::proximity_out(grab, data, handle, event), + } + } + + fn start_data(&self) -> &TabletGrabStartData { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::start_data(grab), + ResizeGrab::Tiling(grab) => TabletToolGrab::start_data(grab), + } + } + + fn unset(&mut self, data: &mut State) { + match self { + ResizeGrab::Floating(grab) => TabletToolGrab::unset(grab, data), + ResizeGrab::Tiling(grab) => TabletToolGrab::unset(grab, data), + } + } +} + pub enum MoveGrab { Move(moving::MoveGrab), Delayed(delay::DelayGrab), @@ -536,10 +680,17 @@ impl MoveGrab { } } - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self { - MoveGrab::Move(m) => m.is_touch_grab(), - MoveGrab::Delayed(d) => d.is_touch_grab(), + MoveGrab::Move(m) => m.grab_type(), + MoveGrab::Delayed(d) => d.grab_type(), + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + match self { + MoveGrab::Move(m) => m.tool(), + MoveGrab::Delayed(d) => d.tool(), } } } @@ -574,11 +725,11 @@ impl PointerGrab for MoveGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { match self { - MoveGrab::Move(grab) => grab.button(data, handle, event), - MoveGrab::Delayed(grab) => grab.button(data, handle, event), + MoveGrab::Move(grab) => PointerGrab::button(grab, data, handle, event), + MoveGrab::Delayed(grab) => PointerGrab::button(grab, data, handle, event), } } @@ -586,11 +737,11 @@ impl PointerGrab for MoveGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { match self { - MoveGrab::Move(grab) => grab.axis(data, handle, details), - MoveGrab::Delayed(grab) => grab.axis(data, handle, details), + MoveGrab::Move(grab) => PointerGrab::axis(grab, data, handle, details), + MoveGrab::Delayed(grab) => PointerGrab::axis(grab, data, handle, details), } } @@ -718,7 +869,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { match self { MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -726,7 +877,12 @@ impl TouchGrab for MoveGrab { } } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { match self { MoveGrab::Move(grab) => TouchGrab::up(grab, data, handle, event), MoveGrab::Delayed(grab) => TouchGrab::up(grab, data, handle, event), @@ -798,3 +954,104 @@ impl TouchGrab for MoveGrab { } } } + +impl TabletToolGrab for MoveGrab { + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::down(grab, data, handle, event), + MoveGrab::Delayed(grab) => TabletToolGrab::down(grab, data, handle, event), + } + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::up(grab, data, handle, event), + MoveGrab::Delayed(grab) => TabletToolGrab::up(grab, data, handle, event), + } + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(PointerFocusTarget, Point)>, + event: &TabletMotionEvent, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::motion(grab, data, handle, focus, event), + MoveGrab::Delayed(grab) => TabletToolGrab::motion(grab, data, handle, focus, event), + } + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + serial: InputTime, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::frame(grab, data, handle, serial), + MoveGrab::Delayed(grab) => TabletToolGrab::frame(grab, data, handle, serial), + } + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::button(grab, data, handle, event), + MoveGrab::Delayed(grab) => TabletToolGrab::button(grab, data, handle, event), + } + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + details: TabletAxisFrame, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::axis(grab, data, handle, details), + MoveGrab::Delayed(grab) => TabletToolGrab::axis(grab, data, handle, details), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::proximity_out(grab, data, handle, event), + MoveGrab::Delayed(grab) => TabletToolGrab::proximity_out(grab, data, handle, event), + } + } + + fn start_data(&self) -> &TabletGrabStartData { + match self { + MoveGrab::Move(grab) => TabletToolGrab::start_data(grab), + MoveGrab::Delayed(grab) => TabletToolGrab::start_data(grab), + } + } + + fn unset(&mut self, data: &mut State) { + match self { + MoveGrab::Move(grab) => TabletToolGrab::unset(grab, data), + MoveGrab::Delayed(grab) => TabletToolGrab::unset(grab, data), + } + } +} diff --git a/src/shell/grabs/moving.rs b/src/shell/grabs/moving.rs index d8714830..f1fbfa8a 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -8,6 +8,7 @@ use crate::{ CosmicMapped, CosmicSurface, Direction, ManagedLayer, element::{CosmicMappedRenderElement, stack_hover::StackHover}, focus::target::{KeyboardFocusTarget, PointerFocusTarget}, + grabs::GrabType, layout::floating::TiledCorners, }, utils::prelude::*, @@ -20,7 +21,7 @@ use smallvec::SmallVec; use smithay::{ backend::{ drm::DrmNode, - input::ButtonState, + input::{ButtonState, InputTime, TabletToolDescriptor}, renderer::{ ImportAll, ImportMem, element::{RenderElement, utils::RescaleRenderElement}, @@ -30,13 +31,27 @@ use smithay::{ input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, - touch::{self, GrabStartData as TouchGrabStartData, TouchGrab, TouchInnerHandle}, + tablet::{ + TabletSeatHandler, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData, + MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent, + TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent, + }, + }, + touch::{ + DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, + MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, + TouchInnerHandle, UpEvent as TouchUpEvent, + }, }, output::Output, utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER, Scale}, @@ -503,7 +518,7 @@ impl PointerGrab for MoveGrab { state: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { self.update_location(state, event.location); @@ -529,7 +544,7 @@ impl PointerGrab for MoveGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(state, event); match self.release { @@ -550,7 +565,7 @@ impl PointerGrab for MoveGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(state, details); } @@ -647,7 +662,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &touch::DownEvent, + event: &TouchDownEvent, ) { handle.down(data, None, event) } @@ -656,7 +671,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &touch::UpEvent, + event: &TouchUpEvent, ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); @@ -670,7 +685,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &touch::MotionEvent, + event: &TouchMotionEvent, ) { if event.slot == >::start_data(self).slot { self.update_location(data, event.location); @@ -691,7 +706,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &touch::ShapeEvent, + event: &ShapeEvent, ) { handle.shape(data, event) } @@ -700,7 +715,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &touch::OrientationEvent, + event: &OrientationEvent, ) { handle.orientation(data, event) } @@ -715,6 +730,98 @@ impl TouchGrab for MoveGrab { fn unset(&mut self, _data: &mut State) {} } +impl TabletToolGrab for MoveGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.proximity_out(data, event); + handle.unset_grab(self, data, event.serial, event.time, false); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + handle.motion(data, None, event); + + self.update_location(data, event.location); + if !self.window.alive() { + handle.unset_grab(self, data, event.serial, event.time, true); + } + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + handle.down(data, event) + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + handle.up(data, event); + handle.unset_grab(self, data, event.serial, event.time, false); + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + handle.button(data, event) + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: TabletAxisFrame, + ) { + handle.axis(data, frame) + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time) + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus, event); + } + + fn unset(&mut self, _data: &mut State) {} +} + impl MoveGrab { pub fn new( start_data: GrabStartData, @@ -778,10 +885,15 @@ impl MoveGrab { self.previous == ManagedLayer::Tiling } - pub fn is_touch_grab(&self) -> bool { - match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + pub fn grab_type(&self) -> GrabType { + self.start_data.type_() + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -793,7 +905,7 @@ impl Drop for MoveGrab { let seat = self.seat.clone(); // false-positive: `Output`s hash is based on it's inner ptr #[allow(clippy::mutable_key_type)] - let window_outputs = self.window_outputs.drain().collect::>(); + let window_outputs = std::mem::take(&mut self.window_outputs); let previous = self.previous; let window = self.window.clone(); let is_touch_grab = matches!(self.start_data, GrabStartData::Touch(_)); @@ -953,10 +1065,10 @@ impl Drop for MoveGrab { position.as_logical().to_f64() - window.geometry().loc.to_f64() + offset, )), - &MotionEvent { + &PointerMotionEvent { location: pointer.current_location(), serial, - time: state.common.clock.now().as_millis(), + time: InputTime::now(), }, ); } diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index f9e5cbfd..9d767671 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -7,25 +7,36 @@ use crate::{ shell::{ element::CosmicMapped, focus::target::PointerFocusTarget, - grabs::{GrabStartData, ReleaseMode, ResizeEdge}, + grabs::{GrabStartData, GrabType, ReleaseMode, ResizeEdge}, }, utils::prelude::*, }; use smithay::{ - backend::input::ButtonState, + backend::input::{ButtonState, InputTime, TabletToolDescriptor}, desktop::{WindowSurface, space::SpaceElement}, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, RelativeMotionEvent, }, + tablet::{ + TabletSeatHandler, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletGrabStartData, + MotionEvent as TabletMotionEvent, ProximityInEvent, ProximityOutEvent, + TabletToolGrab, TabletToolInnerHandle, UpEvent as TabletUpEvent, + }, + }, touch::{ - DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, + DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, + MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, + TouchInnerHandle, UpEvent as TouchUpEvent, }, }, output::Output, @@ -170,10 +181,19 @@ impl ResizeSurfaceGrab { false } - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + GrabStartData::Pointer(_) => GrabType::Pointer, + GrabStartData::Touch(_) => GrabType::Touch, + GrabStartData::TabletTool { .. } => GrabType::TabletTool, + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -184,7 +204,7 @@ impl PointerGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -209,7 +229,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(data, event); match self.release { @@ -230,7 +250,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details) } @@ -329,12 +349,17 @@ impl TouchGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { handle.down(data, None, event) } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -396,6 +421,99 @@ impl TouchGrab for ResizeSurfaceGrab { } } +impl TabletToolGrab for ResizeSurfaceGrab { + fn start_data(&self) -> &TabletGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.unset_grab(self, data, event.serial, event.time, true); + handle.proximity_out(data, event); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + if self.update_location(event.location.as_global()) { + handle.unset_grab(self, data, event.serial, event.time, true); + } + + handle.motion(data, None, event); + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + handle.down(data, event) + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + handle.unset_grab(self, data, event.serial, event.time, true); + handle.up(data, event); + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + handle.button(data, event) + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: TabletAxisFrame, + ) { + handle.axis(data, frame) + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time) + } + + fn unset(&mut self, _data: &mut State) { + self.ungrab() + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, None, event); + } +} + pub struct ResizeGrabMarker(AtomicBool); impl ResizeGrabMarker { diff --git a/src/shell/layout/tiling/grabs/resize.rs b/src/shell/layout/tiling/grabs/resize.rs index 9b135119..c6f202cf 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -4,31 +4,42 @@ use crate::{ backend::render::cursor::CursorState, shell::{ focus::target::PointerFocusTarget, - grabs::{GrabStartData, ReleaseMode}, + grabs::{GrabStartData, GrabType, ReleaseMode}, layout::Orientation, }, utils::prelude::*, }; use id_tree::{NodeId, Tree}; use smithay::{ - backend::input::ButtonState, + backend::input::{ButtonState, InputTime, TabletToolDescriptor}, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, - PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, Focus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, + MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, PointerTarget, + RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatHandler, TabletSeatTrait, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, GrabStartData as TabletToolGrabStartData, + GrabTrigger as TabletToolGrabTrigger, MotionEvent as TabletMotionEvent, + ProximityInEvent, ProximityOutEvent, TabletToolGrab, TabletToolInnerHandle, + TabletToolTarget, UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, GrabStartData as TouchGrabStartData, + DownEvent as TouchDownEvent, FrameMarker, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, TouchTarget, UpEvent, + TouchInnerHandle, TouchTarget, UpEvent as TouchUpEvent, }, }, output::WeakOutput, - utils::{IsAlive, Logical, Point}, + utils::{IsAlive, Logical, Point, Serial}, }; use super::super::{Data, TilingLayout}; @@ -48,7 +59,7 @@ impl IsAlive for ResizeForkTarget { } impl PointerTarget for ResizeForkTarget { - fn enter(&self, seat: &Seat, _data: &mut State, _event: &MotionEvent) { + fn enter(&self, seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); cursor_state @@ -60,19 +71,13 @@ impl PointerTarget for ResizeForkTarget { }); } - fn leave( - &self, - seat: &Seat, - _data: &mut State, - _serial: smithay::utils::Serial, - _time: u32, - ) { + fn leave(&self, seat: &Seat, _data: &mut State, _serial: Serial, _time: InputTime) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); cursor_state.lock().unwrap().unset_shape(); } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { if event.button == 0x110 && event.state == ButtonState::Pressed { let seat = seat.clone(); let node = self.node.clone(); @@ -106,7 +111,7 @@ impl PointerTarget for ResizeForkTarget { } } - fn motion(&self, _seat: &Seat, _data: &mut State, _event: &MotionEvent) {} + fn motion(&self, _seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) {} fn relative_motion( &self, _seat: &Seat, @@ -114,7 +119,7 @@ impl PointerTarget for ResizeForkTarget { _event: &RelativeMotionEvent, ) { } - fn axis(&self, _seat: &Seat, _data: &mut State, _frame: AxisFrame) {} + fn axis(&self, _seat: &Seat, _data: &mut State, _frame: PointerAxisFrame) {} fn frame(&self, _seat: &Seat, _data: &mut State) {} fn gesture_swipe_begin(&self, _: &Seat, _: &mut State, _: &GestureSwipeBeginEvent) {} fn gesture_swipe_update(&self, _: &Seat, _: &mut State, _: &GestureSwipeUpdateEvent) {} @@ -127,7 +132,7 @@ impl PointerTarget for ResizeForkTarget { } impl TouchTarget for ResizeForkTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { let seat = seat.clone(); let node = self.node.clone(); let output = self.output.clone(); @@ -158,7 +163,7 @@ impl TouchTarget for ResizeForkTarget { }); } - fn up(&self, _seat: &Seat, _data: &mut State, _event: &UpEvent) {} + fn up(&self, _seat: &Seat, _data: &mut State, _event: &TouchUpEvent) {} fn motion(&self, _seat: &Seat, _data: &mut State, _event: &TouchMotionEvent) {} fn frame(&self, _seat: &Seat, _data: &mut State, _frame: FrameMarker) {} fn cancel(&self, _seat: &Seat, _data: &mut State, _frame: FrameMarker) {} @@ -169,6 +174,121 @@ impl TouchTarget for ResizeForkTarget { } } +impl TabletToolTarget for ResizeForkTarget { + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletDownEvent, + ) { + let seat = seat.clone(); + let node = self.node.clone(); + let output = self.output.clone(); + let left_up_idx = self.left_up_idx; + let orientation = self.orientation; + let serial = event.serial; + let time = event.time; + let tool = tool_descriptor.clone(); + data.common.event_loop_handle.insert_idle(move |state| { + let pointer = seat.get_pointer().unwrap(); + let location = pointer.current_location(); + let tablet = seat.tablet_seat().get_tool(&tool).unwrap(); + tablet.set_grab( + state, + ResizeForkGrab::new( + GrabStartData::TabletTool { + tool, + data: TabletToolGrabStartData { + focus: None, + location, + trigger: TabletToolGrabTrigger::Tip, + }, + }, + location.as_global(), + node, + left_up_idx, + orientation, + output, + ReleaseMode::NoMouseButtons, + ), + time, + serial, + Focus::Keep, + ) + }); + } + fn motion( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _event: &TabletMotionEvent, + ) { + } + fn proximity_out( + &self, + seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + ) { + let user_data = seat.user_data(); + let cursor_state = user_data.get::().unwrap(); + cursor_state.lock().unwrap().unset_shape(); + } + + fn proximity_in( + &self, + seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _tablet: &Tablet, + _serial: Serial, + ) { + let user_data = seat.user_data(); + let cursor_state = user_data.get::().unwrap(); + cursor_state + .lock() + .unwrap() + .set_shape(match self.orientation { + Orientation::Horizontal => CursorIcon::RowResize, + Orientation::Vertical => CursorIcon::ColResize, + }); + } + fn up( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _event: &TabletUpEvent, + ) { + } + fn axis( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _frame: TabletAxisFrame, + ) { + } + fn button( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _event: &TabletButtonEvent, + ) { + } + fn frame( + &self, + _seat: &Seat, + _data: &mut State, + _tool_descriptor: &TabletToolDescriptor, + _time: InputTime, + ) { + } +} + pub struct ResizeForkGrab { start_data: GrabStartData, last_loc: Point, @@ -338,10 +458,19 @@ impl ResizeForkGrab { false } - pub fn is_touch_grab(&self) -> bool { + pub fn grab_type(&self) -> GrabType { match self.start_data { - GrabStartData::Touch(_) => true, - GrabStartData::Pointer(_) => false, + GrabStartData::Pointer(_) => GrabType::Pointer, + GrabStartData::Touch(_) => GrabType::Touch, + GrabStartData::TabletTool { .. } => GrabType::TabletTool, + } + } + + pub fn tool(&self) -> Option<&TabletToolDescriptor> { + if let GrabStartData::TabletTool { tool, .. } = &self.start_data { + Some(tool) + } else { + None } } } @@ -352,7 +481,7 @@ impl PointerGrab for ResizeForkGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &MotionEvent, + event: &PointerMotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -377,7 +506,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { handle.button(data, event); match self.release { @@ -398,7 +527,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: AxisFrame, + details: PointerAxisFrame, ) { handle.axis(data, details) } @@ -497,12 +626,17 @@ impl TouchGrab for ResizeForkGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &DownEvent, + event: &TouchDownEvent, ) { handle.down(data, None, event) } - fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { + fn up( + &mut self, + data: &mut State, + handle: &mut TouchInnerHandle<'_, State>, + event: &TouchUpEvent, + ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -563,3 +697,96 @@ impl TouchGrab for ResizeForkGrab { self.update_location(data, self.last_loc.as_logical(), true); } } + +impl TabletToolGrab for ResizeForkGrab { + fn start_data(&self) -> &TabletToolGrabStartData { + match &self.start_data { + GrabStartData::TabletTool { data, .. } => data, + _ => unreachable!(), + } + } + + fn proximity_out( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &ProximityOutEvent, + ) { + handle.proximity_out(data, event); + handle.unset_grab(self, data, event.serial, event.time, true); + } + + fn motion( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + _focus: Option<(::ToolFocus, Point)>, + event: &TabletMotionEvent, + ) { + handle.motion(data, None, event); + + if self.update_location(data, event.location, false) { + handle.unset_grab(self, data, event.serial, event.time, true); + } + } + + fn down( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletDownEvent, + ) { + handle.down(data, event); + } + + fn up( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletUpEvent, + ) { + handle.up(data, event); + handle.unset_grab(self, data, event.serial, event.time, true); + } + + fn button( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + event: &TabletButtonEvent, + ) { + handle.button(data, event) + } + + fn axis( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + frame: TabletAxisFrame, + ) { + handle.axis(data, frame) + } + + fn frame( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + time: InputTime, + ) { + handle.frame(data, time) + } + + fn unset(&mut self, data: &mut State) { + self.update_location(data, self.last_loc.as_logical(), true); + } + + fn proximity_in( + &mut self, + data: &mut State, + handle: &mut TabletToolInnerHandle<'_, State>, + focus: Option<(::ToolFocus, Point)>, + event: &ProximityInEvent, + ) { + handle.proximity_in(data, focus, event); + } +} diff --git a/src/shell/layout/tiling/grabs/swap.rs b/src/shell/layout/tiling/grabs/swap.rs index afe93cf0..9ac531d3 100644 --- a/src/shell/layout/tiling/grabs/swap.rs +++ b/src/shell/layout/tiling/grabs/swap.rs @@ -1,6 +1,6 @@ use cosmic_settings_config::shortcuts; use smithay::{ - backend::input::{KeyState, Keycode}, + backend::input::{InputTime, KeyState, Keycode}, input::{ Seat, SeatHandler, keyboard::{ @@ -38,7 +38,7 @@ impl KeyboardGrab for SwapWindowGrab { state: KeyState, modifiers: Option, serial: Serial, - time: u32, + time: InputTime, ) { if !matches!(&data.common.shell.read().overview_mode.active_trigger(), Some(Trigger::KeyboardSwap(_, d)) if d == &self.desc) { diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 2d95cd27..8706dc59 100644 --- a/src/shell/layout/tiling/mod.rs +++ b/src/shell/layout/tiling/mod.rs @@ -3381,7 +3381,7 @@ impl TilingLayout { let Some(root) = tree.root_node_id() else { if matches!( overview.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) && location_f64.is_some() { let mut tree = tree.copy_clone(); @@ -3414,7 +3414,7 @@ impl TilingLayout { if matches!( overview.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { let non_exclusive_zone = layer_map_for_output(&self.output) .non_exclusive_zone() @@ -4062,8 +4062,11 @@ impl TilingLayout { let draw_groups = overview.0.alpha(); let is_overview = !matches!(overview.0, OverviewMode::None); - let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!( + overview.0.trigger(), + Some(Trigger::Pointer(_) | Trigger::Tool(_, _)) + )) + .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { Some(desc.clone()) } else { @@ -4216,8 +4219,11 @@ impl TilingLayout { }; let draw_groups = overview.0.alpha(); - let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!( + overview.0.trigger(), + Some(Trigger::Pointer(_) | Trigger::Tool(_, _)) + )) + .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); let swap_desc = if let Some(Trigger::KeyboardSwap(_, desc)) = overview.0.trigger() { Some(desc.clone()) } else { diff --git a/src/shell/mod.rs b/src/shell/mod.rs index 009c98dc..47d78851 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -32,7 +32,10 @@ use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, Resiz use cosmic_settings_config::{shortcuts, window_rules::ApplicationException}; use keyframe::{ease, functions::EaseInOutCubic}; use smithay::{ - backend::{input::TouchSlot, renderer::element::RenderElementStates}, + backend::{ + input::{TabletToolDescriptor, TouchSlot}, + renderer::element::RenderElementStates, + }, desktop::{ LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output, space::SpaceElement, @@ -46,6 +49,7 @@ use smithay::{ pointer::{ CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData, }, + tablet::{TabletSeatTrait, tool::GrabTrigger as TabletGrabTrigger}, }, output::{Output, WeakOutput}, reexports::{ @@ -130,6 +134,7 @@ pub enum Trigger { KeyboardMove(shortcuts::Modifiers), Pointer(u32), Touch(TouchSlot), + Tool(TabletToolDescriptor, TabletGrabTrigger), } #[derive(Debug, Clone)] @@ -254,6 +259,7 @@ pub struct PendingWindow { pub surface: CosmicSurface, pub seat: Seat, pub fullscreen: Option, + pub minimized: bool, pub maximized: bool, pub sticky: bool, } @@ -1754,7 +1760,7 @@ impl Shell { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( self.overview_mode.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -1805,7 +1811,7 @@ impl Shell { if let Some(set) = self.workspaces.sets.get_mut(output) { if matches!( self.overview_mode.active_trigger(), - Some(Trigger::Pointer(_) | Trigger::Touch(_)) + Some(Trigger::Pointer(_) | Trigger::Touch(_) | Trigger::Tool(_, _)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -2856,6 +2862,7 @@ impl Shell { surface: window, seat, fullscreen: output, + minimized: should_be_minimized, maximized: should_be_maximized, sticky: mut should_be_sticky, } = self.pending_windows.remove(pos); @@ -2939,6 +2946,7 @@ impl Shell { if let Some(FocusTarget::Window(focused)) = maybe_focused && let Some(stack) = focused.stack_ref() && !is_dialog + && !should_be_minimized && !should_be_maximized && !(workspace.is_tiled(&focused.active_window()) && floating_exception) { @@ -2988,8 +2996,13 @@ impl Shell { self.maximize_request(&mapped, &seat, false, loop_handle); } - let new_target = if (workspace_output == seat.active_output() - && active_handle == workspace_handle) + if should_be_minimized { + self.minimize_request(&window); + } + + let new_target = if should_be_minimized { + None + } else if (workspace_output == seat.active_output() && active_handle == workspace_handle) || should_be_sticky { // TODO: enforce focus stealing prevention by also checking the same rules as for the else case. @@ -3113,6 +3126,7 @@ impl Shell { surface, seat: seat.clone(), fullscreen: None, + minimized: false, maximized: false, sticky: false, }); @@ -3831,6 +3845,7 @@ impl Shell { let trigger = match &start_data { GrabStartData::Pointer(start_data) => Trigger::Pointer(start_data.button), GrabStartData::Touch(start_data) => Trigger::Touch(start_data.slot), + GrabStartData::TabletTool { tool, data } => Trigger::Tool(tool.clone(), data.trigger), }; let active_hint = if config.cosmic_conf.active_hint { self.theme.cosmic().active_hint as u8 @@ -5149,10 +5164,19 @@ pub fn check_grab_preconditions( let pointer = seat.get_pointer().unwrap(); let touch = seat.get_touch().unwrap(); + let tablet = seat.tablet_seat(); + let tools = tablet.get_tools(); let start_data = if serial.is_some_and(|serial| touch.has_grab(serial)) { GrabStartData::Touch(touch.grab_start_data().unwrap()) + } else if let Some((desc, tool)) = + serial.and_then(|serial| tools.iter().find(|(_, tool)| tool.has_grab(serial))) + { + GrabStartData::TabletTool { + tool: desc.clone(), + data: tool.grab_start_data().unwrap(), + } } else { GrabStartData::Pointer(pointer.grab_start_data().unwrap_or_else(|| { PointerGrabStartData { @@ -5166,8 +5190,16 @@ pub fn check_grab_preconditions( if let Some(surface) = client_initiated { // Check that this surface has a click or touch down grab. if !match serial { - Some(serial) => pointer.has_grab(serial) || touch.has_grab(serial), - None => pointer.is_grabbed() | touch.is_grabbed(), + Some(serial) => { + pointer.has_grab(serial) + || touch.has_grab(serial) + || tools.values().any(|tool| tool.has_grab(serial)) + } + None => { + pointer.is_grabbed() + || touch.is_grabbed() + || tools.values().any(|tool| tool.is_grabbed()) + } } { return None; } diff --git a/src/shell/zoom.rs b/src/shell/zoom.rs index 25a16e9c..dcddfb27 100644 --- a/src/shell/zoom.rs +++ b/src/shell/zoom.rs @@ -11,19 +11,31 @@ use cosmic_comp_config::{ZoomConfig, ZoomMovement}; use cosmic_config::ConfigSet; use keyframe::{ease, functions::Linear}; use smithay::{ - backend::renderer::ImportMem, + backend::{ + input::{InputTime, TabletToolDescriptor}, + renderer::ImportMem, + }, desktop::space::SpaceElement, input::{ Seat, pointer::{ - AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, - MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, Focus, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + PointerTarget, RelativeMotionEvent, + }, + tablet::{ + Tablet, TabletSeatTrait, + tool::{ + AxisFrame as TabletAxisFrame, ButtonEvent as TabletButtonEvent, + DownEvent as TabletDownEvent, MotionEvent as TabletMotionEvent, TabletToolTarget, + UpEvent as TabletUpEvent, + }, }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -33,6 +45,7 @@ use tracing::error; use crate::{ backend::render::element::AsGlowRenderer, + shell::grabs::GrabType, state::State, utils::{ iced::{IcedElement, IcedRenderElement, Program}, @@ -699,15 +712,27 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( state, grab, serial, Focus::Clear, - ); + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + state, + grab, + InputTime::now(), + serial, + Focus::Clear, + ), } } } @@ -786,15 +811,27 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(state, grab, serial); - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch().unwrap().set_grab(state, grab, serial) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( state, grab, serial, Focus::Clear, - ); + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + state, + grab, + InputTime::now(), + serial, + Focus::Clear, + ), } } } @@ -884,14 +921,14 @@ impl PointerTarget for ZoomFocusTarget { } } - fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::button(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => PointerTarget::button(elem, seat, data, event), } } - fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame), @@ -1024,7 +1061,7 @@ impl PointerTarget for ZoomFocusTarget { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::leave(elem, seat, data, serial, time), ZoomFocusTarget::Menu(elem) => PointerTarget::leave(elem, seat, data, serial, time), @@ -1033,14 +1070,14 @@ impl PointerTarget for ZoomFocusTarget { } impl TouchTarget for ZoomFocusTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { match self { ZoomFocusTarget::Main(elem) => TouchTarget::down(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::down(elem, seat, data, event), } } - fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { match self { ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event), @@ -1090,6 +1127,144 @@ impl TouchTarget for ZoomFocusTarget { } } +impl TabletToolTarget for ZoomFocusTarget { + fn proximity_in( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + tablet: &Tablet, + serial: Serial, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::proximity_in(elem, seat, data, tool_descriptor, tablet, serial) + } + } + } + + fn proximity_out( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::proximity_out(elem, seat, data, tool_descriptor) + } + } + } + + fn down( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletDownEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::down(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::down(elem, seat, data, tool_descriptor, event) + } + } + } + + fn up( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletUpEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::up(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::up(elem, seat, data, tool_descriptor, event) + } + } + } + + fn motion( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletMotionEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::motion(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::motion(elem, seat, data, tool_descriptor, event) + } + } + } + + fn axis( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + frame: TabletAxisFrame, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::axis(elem, seat, data, tool_descriptor, frame) + } + } + } + + fn button( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + event: &TabletButtonEvent, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::button(elem, seat, data, tool_descriptor, event) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::button(elem, seat, data, tool_descriptor, event) + } + } + } + + fn frame( + &self, + seat: &Seat, + data: &mut State, + tool_descriptor: &TabletToolDescriptor, + time: InputTime, + ) { + match self { + ZoomFocusTarget::Main(elem) => { + TabletToolTarget::frame(elem, seat, data, tool_descriptor, time) + } + ZoomFocusTarget::Menu(elem) => { + TabletToolTarget::frame(elem, seat, data, tool_descriptor, time) + } + } + } +} + impl IsAlive for ZoomFocusTarget { fn alive(&self) -> bool { match self { diff --git a/src/state.rs b/src/state.rs index 5ccc7a7b..28ed8fd4 100644 --- a/src/state.rs +++ b/src/state.rs @@ -1328,8 +1328,12 @@ impl Common { const THROTTLE: Option = Some(Duration::from_millis(995)); const SCREENCOPY_THROTTLE: Option = Some(Duration::from_nanos(16_666_666)); - fn throttle(session_holder: &impl SessionHolder) -> Option { - if session_holder.sessions().is_empty() && session_holder.cursor_sessions().is_empty() { + fn throttle(session_holder: &impl SessionHolder, is_xwayland: bool) -> Option { + if is_xwayland { + Some(Duration::ZERO) + } else if session_holder.sessions().is_empty() + && session_holder.cursor_sessions().is_empty() + { THROTTLE } else { SCREENCOPY_THROTTLE @@ -1365,7 +1369,8 @@ impl Common { && let Some(grab_state) = move_grab.lock().unwrap().as_ref() { for (window, _) in grab_state.element().windows() { - window.send_frame(output, time, throttle(&window), should_send); + let throttle = throttle(&window, window.x11_surface().is_some()); + window.send_frame(output, time, throttle, should_send); } } @@ -1389,25 +1394,28 @@ impl Common { .mapped() .for_each(|mapped| { for (window, _) in mapped.windows() { - window.send_frame(output, time, throttle(&window), should_send); + let throttle = throttle(&window, window.x11_surface().is_some()); + window.send_frame(output, time, throttle, should_send); } }); if let Some(active) = shell.active_space(output) { if let Some(fs) = active.get_fullscreen(shell.seats.last_active()) { - fs.surface - .send_frame(output, time, throttle(&fs.surface), should_send); + let throttle = throttle(&fs.surface, fs.surface.x11_surface().is_some()); + fs.surface.send_frame(output, time, throttle, should_send); } active.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { - window.send_frame(output, time, throttle(&window), should_send); + let throttle = throttle(&window, window.x11_surface().is_some()); + window.send_frame(output, time, throttle, should_send); } }); // other (throttled) windows active.minimized_windows.iter().for_each(|m| { for window in m.windows() { - window.send_frame(output, time, throttle(&window), |_, _| None); + let throttle = throttle(&window, window.x11_surface().is_some()); + window.send_frame(output, time, throttle, |_, _| None); } }); @@ -1417,18 +1425,25 @@ impl Common { .filter(|w| w.handle != active.handle) { if let Some(fs) = space.get_fullscreen(shell.seats.last_active()) { - let throttle = min(throttle(space), throttle(&fs.surface)); + let throttle = min( + throttle(space, false), + throttle(&fs.surface, fs.surface.x11_surface().is_some()), + ); fs.surface.send_frame(output, time, throttle, |_, _| None); } space.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { - let throttle = min(throttle(space), throttle(&window)); + let throttle = min( + throttle(space, false), + throttle(&window, window.x11_surface().is_some()), + ); window.send_frame(output, time, throttle, |_, _| None); } }); space.minimized_windows.iter().for_each(|m| { for window in m.windows() { - window.send_frame(output, time, throttle(&window), |_, _| None); + let throttle = throttle(&window, window.x11_surface().is_some()); + window.send_frame(output, time, throttle, |_, _| None); } }) } diff --git a/src/utils/iced/mod.rs b/src/utils/iced/mod.rs index 2bfe888d..4522644b 100644 --- a/src/utils/iced/mod.rs +++ b/src/utils/iced/mod.rs @@ -31,7 +31,7 @@ use ordered_float::OrderedFloat; use smithay::{ backend::{ allocator::Fourcc, - input::{ButtonState, KeyState}, + input::{ButtonState, InputTime, KeyState, TabletToolDescriptor}, renderer::{ ImportMem, element::{ @@ -45,14 +45,23 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, - GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, - GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, + GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, + GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, + GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, + tablet::{ + Tablet, + tool::{ + AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, + DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, + UpEvent as ToolUpEvent, + }, + }, touch::{ - DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, - TouchTarget, UpEvent, + DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, }, }, output::Output, @@ -189,6 +198,7 @@ pub(crate) struct IcedElementInternal { touch_map: HashMap, last_touch_frame: Option, last_touch_serial: Option, + last_tablet_serial: Option, // iced theme: Theme, @@ -240,6 +250,7 @@ impl Clone for IcedElementInternal

{ touch_map: self.touch_map.clone(), last_touch_frame: None, last_touch_serial: None, + last_tablet_serial: None, theme: self.theme.clone(), renderer, state, @@ -267,6 +278,7 @@ impl fmt::Debug for IcedElementInternal

{ .field("touch_map", &self.touch_map) .field("last_touch_frame", &self.last_touch_frame) .field("last_touch_serial", &self.last_touch_serial) + .field("last_tablet_serial", &self.last_tablet_serial) .field("theme", &"...") .field("renderer", &"...") .field("state", &"...") @@ -326,6 +338,7 @@ impl IcedElement

{ touch_map: HashMap::new(), last_touch_frame: None, last_touch_serial: None, + last_tablet_serial: None, theme, renderer, state, @@ -481,12 +494,143 @@ impl IcedElementInternal

{ } } +impl TabletToolTarget for IcedElement

{ + fn proximity_in( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _tablet: &Tablet, + serial: Serial, + ) { + let mut internal = self.0.lock().unwrap(); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorEntered)); + internal.last_tablet_serial = Some(serial); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), serial)); + internal.update(false); + } + + fn proximity_out( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + ) { + let mut internal = self.0.lock().unwrap(); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorLeft)); + internal.update(false); + } + + fn down( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolDownEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(0); + let Some(event_location) = internal.cursor_pos else { + return; + }; + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerPressed { id, position })); + internal.last_tablet_serial = Some(event.serial); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial)); + internal.update(false); + } + + fn up( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _event: &ToolUpEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let id = Finger(0); + if let Some(event_location) = internal.cursor_pos { + *internal.last_seat.lock().unwrap() = + Some((seat.clone(), internal.last_tablet_serial.unwrap())); + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Touch(TouchEvent::FingerLifted { id, position })); + internal.update(false); + } + } + + fn motion( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolMotionEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let event_location = event.location.downscale(internal.additional_scale); + let position = IcedPoint::new(event_location.x as f32, event_location.y as f32); + internal + .state + .queue_event(Event::Mouse(MouseEvent::CursorMoved { position })); + internal.cursor_pos = Some(event_location); + *internal.last_seat.lock().unwrap() = + Some((seat.clone(), internal.last_tablet_serial.unwrap())); + internal.update(false); + } + + fn axis( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _frame: ToolAxisFrame, + ) { + } + + fn button( + &self, + seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + event: &ToolButtonEvent, + ) { + let mut internal = self.0.lock().unwrap(); + let button = match event.button { + 0x14b => MouseButton::Right, + 0x14c => MouseButton::Middle, + _ => return, + }; + internal.state.queue_event(Event::Mouse(match event.state { + ButtonState::Pressed => MouseEvent::ButtonPressed(button), + ButtonState::Released => MouseEvent::ButtonReleased(button), + })); + *internal.last_seat.lock().unwrap() = Some((seat.clone(), event.serial)); + internal.update(false); + } + + fn frame( + &self, + _seat: &Seat, + _data: &mut crate::state::State, + _tool_descriptor: &TabletToolDescriptor, + _time: InputTime, + ) { + } +} + impl PointerTarget for IcedElement

{ fn enter( &self, seat: &Seat, _data: &mut crate::state::State, - event: &MotionEvent, + event: &PointerMotionEvent, ) { let mut internal = self.0.lock().unwrap(); internal @@ -507,7 +651,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &MotionEvent, + event: &PointerMotionEvent, ) { let mut internal = self.0.lock().unwrap(); let event_location = event.location.downscale(internal.additional_scale); @@ -532,7 +676,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &ButtonEvent, + event: &PointerButtonEvent, ) { let mut internal = self.0.lock().unwrap(); let button = match event.button { @@ -553,7 +697,7 @@ impl PointerTarget for IcedEle &self, _seat: &Seat, _data: &mut crate::state::State, - frame: AxisFrame, + frame: PointerAxisFrame, ) { let mut internal = self.0.lock().unwrap(); internal @@ -581,7 +725,7 @@ impl PointerTarget for IcedEle _seat: &Seat, _data: &mut crate::state::State, _serial: Serial, - _time: u32, + _time: InputTime, ) { let mut internal = self.0.lock().unwrap(); internal @@ -653,7 +797,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &DownEvent, + event: &TouchDownEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); @@ -673,7 +817,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &UpEvent, + event: &TouchUpEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); @@ -784,7 +928,7 @@ impl KeyboardTarget for IcedEl _key: KeysymHandle<'_>, _state: KeyState, _serial: Serial, - _time: u32, + _time: InputTime, ) { // TODO convert keys } diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index 12bc2e56..ed40448b 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -3,9 +3,12 @@ use crate::{shell::grabs::SeatMoveGrabState, state::ClientState, utils::prelude::*}; use calloop::Interest; use smithay::{ - backend::renderer::{ - element::{Kind, surface::KindEvaluation}, - utils::{on_commit_buffer_handler, with_renderer_surface_state}, + backend::{ + input::InputTime, + renderer::{ + element::{Kind, surface::KindEvaluation}, + utils::{on_commit_buffer_handler, with_renderer_surface_state}, + }, }, desktop::{LayerSurface, PopupKind, WindowSurfaceType, layer_map_for_output}, reexports::wayland_server::{Client, Resource, protocol::wl_surface::WlSurface}, @@ -325,9 +328,11 @@ impl CompositorHandler for State { } } else { std::mem::drop(shell); - seat.get_pointer() - .unwrap() - .unset_grab(self, SERIAL_COUNTER.next_serial(), 0); + seat.get_pointer().unwrap().unset_grab( + self, + SERIAL_COUNTER.next_serial(), + InputTime::now(), + ); return; } } diff --git a/src/wayland/handlers/corner_radius.rs b/src/wayland/handlers/corner_radius.rs index ded8d923..1a541938 100644 --- a/src/wayland/handlers/corner_radius.rs +++ b/src/wayland/handlers/corner_radius.rs @@ -45,18 +45,11 @@ pub fn surface_corners(states: &SurfaceData, size: Size) -> Option ]) } -pub fn surface_padding(states: &SurfaceData, size: Size) -> Option<[i32; 4]> { +pub fn surface_padding(states: &SurfaceData) -> Option<[i32; 4]> { let mut guard = states.cached_state.get::(); let padding = guard.current().0?; - - // guard against padding being too large - Some([ - padding.top.min(size.h / 2), - padding.right.min(size.w / 2), - padding.bottom.min(size.h / 2), - padding.left.min(size.w / 2), - ]) + Some([padding.top, padding.right, padding.bottom, padding.left]) } pub fn pad_rect( diff --git a/src/wayland/handlers/decoration.rs b/src/wayland/handlers/decoration.rs index 90ec5855..a1efbd0a 100644 --- a/src/wayland/handlers/decoration.rs +++ b/src/wayland/handlers/decoration.rs @@ -1,5 +1,6 @@ use std::{cell::RefCell, sync::Mutex}; +use cosmic_comp_config::DecorationPreference; use smithay::{ desktop::Window, reexports::{ @@ -20,7 +21,7 @@ use smithay::{ }; use wayland_backend::protocol::WEnum; -use crate::state::State; +use crate::{shell::CosmicMapped, state::State}; pub struct PreferredDecorationMode(RefCell>); @@ -29,7 +30,7 @@ impl PreferredDecorationMode { window .user_data() .get::() - .is_none() + .is_none_or(|mode| mode.0.borrow().is_none()) } pub fn mode(window: &Window) -> Option { @@ -53,6 +54,72 @@ impl PreferredDecorationMode { } } +impl State { + pub fn default_decoration(&self) -> DecorationPreference { + self.common.config.cosmic_conf.decoration_preference + } + + pub fn update_decorations(&self) { + let shell = self.common.shell.read(); + + let update = |mapped: &CosmicMapped| { + let mode = if mapped.is_stack() { + XdgMode::ServerSide + } else { + XdgMode::from_preference(self.default_decoration()) + }; + for (window, _) in mapped.windows() { + if PreferredDecorationMode::is_unset(&window.0) + && let Some(toplevel) = window.0.toplevel() + && toplevel.with_committed_state(|state| { + state.is_some_and(|state| state.decoration_mode.is_some()) + }) + { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(mode); + }); + toplevel.send_configure(); + } + } + }; + + for set in shell.workspaces.sets.values() { + set.sticky_layer.mapped().for_each(update); + } + + for space in shell.workspaces.spaces() { + space.mapped().for_each(update); + space + .minimized_windows + .iter() + .filter_map(|m| m.mapped()) + .for_each(update); + } + } +} + +trait FromDecorationPreference { + fn from_preference(preference: DecorationPreference) -> Self; +} + +impl FromDecorationPreference for XdgMode { + fn from_preference(preference: DecorationPreference) -> Self { + match preference { + DecorationPreference::ClientSide => XdgMode::ClientSide, + DecorationPreference::ServerSide => XdgMode::ServerSide, + } + } +} + +impl FromDecorationPreference for KdeMode { + fn from_preference(preference: DecorationPreference) -> Self { + match preference { + DecorationPreference::ClientSide => KdeMode::Client, + DecorationPreference::ServerSide => KdeMode::Server, + } + } +} + pub type KdeDecorationData = Mutex; #[derive(Debug, Default)] pub struct KdeDecorationSurfaceState { @@ -67,7 +134,7 @@ impl XdgDecorationHandler for State { let mode = if mapped.is_stack() { XdgMode::ServerSide } else { - XdgMode::ClientSide + XdgMode::from_preference(self.default_decoration()) }; if let Some((window, _)) = mapped @@ -80,6 +147,10 @@ impl XdgDecorationHandler for State { }); toplevel.send_configure(); } + } else { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(XdgMode::from_preference(self.default_decoration())) + }) } } @@ -99,6 +170,13 @@ impl XdgDecorationHandler for State { } } else { toplevel.with_pending_state(|state| state.decoration_mode = Some(mode)); + if let Some(pending) = shell + .pending_windows + .iter() + .find(|pending| pending.surface.0.toplevel().is_some_and(|t| t == &toplevel)) + { + PreferredDecorationMode::update(&pending.surface.0, Some(mode)); + } } } @@ -110,11 +188,28 @@ impl XdgDecorationHandler for State { .find(|(window, _)| window.wl_surface().as_deref() == Some(toplevel.wl_surface())) && let Some(toplevel) = window.0.toplevel() { + let mode = if mapped.is_stack() { + XdgMode::ServerSide + } else { + XdgMode::from_preference(self.default_decoration()) + }; + PreferredDecorationMode::update(&window.0, None); toplevel.with_pending_state(|state| { - state.decoration_mode = None; + state.decoration_mode = Some(mode); }); toplevel.send_configure(); + } else { + toplevel.with_pending_state(|state| { + state.decoration_mode = Some(XdgMode::from_preference(self.default_decoration())) + }); + if let Some(pending) = shell + .pending_windows + .iter() + .find(|pending| pending.surface.0.toplevel().is_some_and(|t| t == &toplevel)) + { + PreferredDecorationMode::update(&pending.surface.0, None); + } } } } @@ -129,10 +224,10 @@ impl KdeDecorationHandler for State { if mapped.is_stack() { KdeMode::Server } else { - KdeMode::Client + KdeMode::from_preference(self.default_decoration()) } } else { - KdeMode::Client + KdeMode::from_preference(self.default_decoration()) }; with_states(surface, |states| { diff --git a/src/wayland/handlers/keyboard_layout.rs b/src/wayland/handlers/keyboard_layout.rs index ac1fda87..2477f93b 100644 --- a/src/wayland/handlers/keyboard_layout.rs +++ b/src/wayland/handlers/keyboard_layout.rs @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only +use smithay::input::keyboard::KeyboardHandle; + use crate::state::State; use crate::wayland::protocols::keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState}; @@ -7,4 +9,8 @@ impl KeyboardLayoutHandler for State { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState { &mut self.common.keyboard_layout_state } + + fn group_changed(&mut self, keyboard: &KeyboardHandle) { + self.broadcast_ei_keyboard_modifiers(keyboard); + } } diff --git a/src/wayland/handlers/pointer_constraints.rs b/src/wayland/handlers/pointer_constraints.rs index 9ce5f63a..743b3b0b 100644 --- a/src/wayland/handlers/pointer_constraints.rs +++ b/src/wayland/handlers/pointer_constraints.rs @@ -5,7 +5,10 @@ use smithay::{ input::pointer::PointerHandle, reexports::wayland_server::protocol::wl_surface::WlSurface, utils::{Logical, Point}, - wayland::{pointer_constraints::PointerConstraintsHandler, seat::WaylandFocus}, + wayland::{ + pointer_constraints::{ConstraintRemove, PointerConstraintsHandler}, + seat::WaylandFocus, + }, }; pub use smithay::wayland::pointer_constraints::{PointerConstraintRef, with_pointer_constraint}; @@ -76,23 +79,37 @@ impl PointerConstraintsHandler for State { } } - fn remove_constraint(&mut self, surface: &WlSurface, pointer: &PointerHandle) { - if with_pointer_constraint(surface, pointer, |constraint| constraint.is_none()) { - let seat = self - .common - .shell - .read() - .seats - .iter() - .find(|s| s.get_pointer().as_ref() == Some(pointer)) - .cloned(); + fn remove_constraint( + &mut self, + surface: &WlSurface, + pointer: &PointerHandle, + constraint_remove: ConstraintRemove, + ) { + match constraint_remove { + ConstraintRemove::PointerLeave(_) => { + // If the constraint was broken by the pointer forcibly leaving the surface, then it doesn't + // make much sense to warp it. + } + ConstraintRemove::Destroyed(constraint) => { + let Some(seat) = self + .common + .shell + .read() + .seats + .iter() + .find(|s| s.get_pointer().as_ref() == Some(pointer)) + .cloned() + else { + return; + }; + let Some((hint_surface, hint_location)) = seat.pointer_constraint_hint() else { + return; + }; - if let Some(seat) = seat - && let Some((hint_surface, hint_location)) = seat.pointer_constraint_hint() - && hint_surface == *surface - { - self.apply_cursor_hint(surface, pointer, hint_location); - seat.set_pointer_constraint_hint(None); + if hint_surface == *surface { + self.apply_cursor_hint(surface, pointer, hint_location, Some(&constraint)); + seat.set_pointer_constraint_hint(None); + } } } } diff --git a/src/wayland/handlers/pointer_warp.rs b/src/wayland/handlers/pointer_warp.rs index 971ab583..634817cf 100644 --- a/src/wayland/handlers/pointer_warp.rs +++ b/src/wayland/handlers/pointer_warp.rs @@ -38,7 +38,7 @@ impl PointerWarpHandler for State { drop(shell); if let Some(pointer_handle) = pointer_handle { - self.apply_cursor_hint(&surface, &pointer_handle, pos); + self.apply_cursor_hint(&surface, &pointer_handle, pos, None); } } } diff --git a/src/wayland/handlers/tablet_manager.rs b/src/wayland/handlers/tablet_manager.rs index e4b84434..7cf2b8cb 100644 --- a/src/wayland/handlers/tablet_manager.rs +++ b/src/wayland/handlers/tablet_manager.rs @@ -1,13 +1,13 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::state::State; +use crate::{shell::focus::target::PointerFocusTarget, state::State}; use smithay::{ backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus, - input::tablet::TabletSeatHandler, reexports::wayland_server::protocol::wl_surface, + input::tablet::TabletSeatHandler, }; impl TabletSeatHandler for State { - type ToolFocus = wl_surface::WlSurface; + type ToolFocus = PointerFocusTarget; fn tablet_tool_image(&mut self, _tool: &TabletToolDescriptor, _image: CursorImageStatus) { // TODO display cursor for each tablet tool diff --git a/src/wayland/handlers/toplevel_management.rs b/src/wayland/handlers/toplevel_management.rs index 3da39952..b1616bca 100644 --- a/src/wayland/handlers/toplevel_management.rs +++ b/src/wayland/handlers/toplevel_management.rs @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only use smithay::{ + backend::input::InputTime, desktop::{WindowSurfaceType, layer_map_for_output}, input::{Seat, pointer::MotionEvent}, output::Output, @@ -124,7 +125,7 @@ impl ToplevelManagementHandler for State { &MotionEvent { location: new_pos.to_f64().as_logical(), serial, - time: self.common.clock.now().as_millis(), + time: InputTime::now(), }, ); ptr.frame(self); diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index b4f16c4c..be7084dd 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -1,11 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::{ - shell::{CosmicSurface, PendingWindow, focus::target::KeyboardFocusTarget, grabs::ReleaseMode}, + shell::{ + CosmicSurface, PendingWindow, + focus::target::KeyboardFocusTarget, + grabs::{GrabType, ReleaseMode}, + }, utils::prelude::*, }; -use smithay::desktop::layer_map_for_output; use smithay::{ + backend::input::InputTime, desktop::{ PopupGrab, PopupKeyboardGrab, PopupKind, PopupPointerGrab, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface, @@ -26,6 +30,7 @@ use smithay::{ }, }, }; +use smithay::{desktop::layer_map_for_output, input::tablet::TabletSeatTrait}; use std::cell::Cell; use tracing::warn; @@ -50,6 +55,7 @@ impl XdgShellHandler for State { surface, seat, fullscreen: None, + minimized: false, maximized: false, sticky: false, }) @@ -189,12 +195,17 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(self, grab, serial); - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(self, grab, serial, focus) + .set_grab(self, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(self, grab, InputTime::now(), serial, focus), } } } @@ -217,12 +228,17 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch().unwrap().set_grab(self, grab, serial) - } else { - seat.get_pointer() + match grab.grab_type() { + GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), + GrabType::Pointer => seat + .get_pointer() .unwrap() - .set_grab(self, grab, serial, focus) + .set_grab(self, grab, serial, focus), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab(self, grab, InputTime::now(), serial, focus), } } } diff --git a/src/wayland/protocols/corner_radius.rs b/src/wayland/protocols/corner_radius.rs index 51dc1153..5c1a200c 100644 --- a/src/wayland/protocols/corner_radius.rs +++ b/src/wayland/protocols/corner_radius.rs @@ -5,17 +5,19 @@ use cosmic_protocols::corner_radius::v1::server::cosmic_corner_radius_toplevel_v use cosmic_protocols::corner_radius::v1::server::{ cosmic_corner_radius_manager_v1, cosmic_corner_radius_toplevel_v1, }; -use smithay::desktop::utils::bbox_from_surface_tree; +use smithay::backend::renderer::buffer_dimensions; +use smithay::backend::renderer::utils::RendererSurfaceStateUserData; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_popup::XdgPopup; use smithay::reexports::wayland_protocols_wlr::layer_shell::v1::server::zwlr_layer_surface_v1::ZwlrLayerSurfaceV1; use smithay::reexports::wayland_server::New; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; -use smithay::utils::{HookId, Logical, Point, Rectangle}; -use smithay::wayland::compositor::Cacheable; +use smithay::utils::{HookId, Logical, Rectangle}; use smithay::wayland::compositor::add_pre_commit_hook; use smithay::wayland::compositor::with_states; +use smithay::wayland::compositor::{BufferAssignment, Cacheable, SurfaceAttributes}; use smithay::wayland::shell::wlr_layer::WlrLayerShellHandler; use smithay::wayland::shell::xdg::{SurfaceCachedState, XdgShellSurfaceUserData}; +use smithay::wayland::viewporter::ViewportCachedState; use smithay::{ reexports::{ wayland_protocols::xdg::shell::server::xdg_toplevel::XdgToplevel, @@ -655,7 +657,6 @@ fn pad_rect( } fn layer_radius_hook(_state: &mut D, _dh: &DisplayHandle, surface: &WlSurface) { - let bbox = bbox_from_surface_tree(surface, Point::default()); with_states(surface, |surface_data| { let corners = *surface_data .cached_state @@ -665,8 +666,40 @@ fn layer_radius_hook(_state: &mut D, _dh: &DisplayHandle, surface: & .cached_state .get::() .pending(); + + // The wl_surface size after this commit is: + // - viewport destination if set + // - else the logical size of the buffer that will be current attached now + // - else existing + let size = surface_data + .cached_state + .get::() + .pending() + .size() + .or_else(|| { + let mut guard = surface_data.cached_state.get::(); + let attrs = guard.pending(); + match &attrs.buffer { + Some(BufferAssignment::NewBuffer(buffer)) => buffer_dimensions(buffer) + .map(|d| d.to_logical(attrs.buffer_scale, attrs.buffer_transform.into())), + _ => None, + } + }) + .or_else(|| { + surface_data + .data_map + .get::() + .and_then(|state| state.lock().unwrap().surface_size()) + }); + let Some(size) = size else { + return; + }; + let empty = Padding::default(); - let Some(padded_box) = pad_rect(bbox, padding.0.as_ref().unwrap_or(&empty)) else { + let Some(padded_box) = pad_rect( + Rectangle::from_size(size), + padding.0.as_ref().unwrap_or(&empty), + ) else { if let Some(hook) = surface_data.data_map.get::() { let hook_ref = hook.lock().unwrap(); if let Some((_, obj)) = hook_ref.as_ref() diff --git a/src/wayland/protocols/keyboard_layout.rs b/src/wayland/protocols/keyboard_layout.rs index f3a44f0a..8a8840b6 100644 --- a/src/wayland/protocols/keyboard_layout.rs +++ b/src/wayland/protocols/keyboard_layout.rs @@ -17,8 +17,10 @@ use smithay::{ use std::mem; use wayland_backend::server::{ClientId, GlobalId}; -pub trait KeyboardLayoutHandler { +pub trait KeyboardLayoutHandler: SeatHandler { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState; + /// Group has been changed through the protocol + fn group_changed(&mut self, keyboard: &KeyboardHandle); } #[derive(Debug)] @@ -57,6 +59,7 @@ impl KeyboardLayoutState { let active_layout = handle.with_xkb_state(state, |context| { context.xkb().lock().unwrap().active_layout() }); + state.group_changed(handle); if *last_layout != Some(active_layout) { keyboard_layout.group(active_layout.0); *last_layout = Some(active_layout); diff --git a/src/wayland/protocols/toplevel_info.rs b/src/wayland/protocols/toplevel_info.rs index 2dc76347..3146adc3 100644 --- a/src/wayland/protocols/toplevel_info.rs +++ b/src/wayland/protocols/toplevel_info.rs @@ -418,6 +418,12 @@ where handle.closed(); } } + // Remove the foreign handle too, so new subscribers cannot + // discover a toplevel whose window has already been destroyed. + if let Some(handle) = state.foreign_handle.take() { + self.foreign_toplevel_list.remove_toplevel(&handle); + } + *state = Default::default(); dirty = true; false } diff --git a/src/xwayland.rs b/src/xwayland.rs index da3fb36b..cc6be3b4 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -9,7 +9,9 @@ use std::{ use crate::{ backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme}, shell::{ - CosmicSurface, PendingWindow, Shell, focus::target::KeyboardFocusTarget, grabs::ReleaseMode, + CosmicSurface, PendingWindow, Shell, + focus::target::KeyboardFocusTarget, + grabs::{GrabType, ReleaseMode}, }, state::State, utils::prelude::*, @@ -20,7 +22,7 @@ use smithay::{ backend::{ allocator::Fourcc, drm::DrmNode, - input::{ButtonState, KeyState, Keycode}, + input::{ButtonState, InputTime, KeyState, Keycode}, renderer::{ Bind, Frame, Offscreen, Renderer, element::{ @@ -32,7 +34,7 @@ use smithay::{ }, }, desktop::space::SpaceElement, - input::{keyboard::ModifiersState, pointer::CursorIcon}, + input::{keyboard::ModifiersState, pointer::CursorIcon, tablet::TabletSeatTrait}, reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window}, utils::{ Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform, @@ -396,7 +398,7 @@ impl Common { state: KeyState, modifiers: ModifiersState, serial: Serial, - time: u32, + time: InputTime, ) { let config = self.config.cosmic_conf.xwayland_eavesdropping.keyboard; if config == EavesdroppingKeyboardMode::None { @@ -458,7 +460,7 @@ impl Common { tracing::trace!("Forwaring key {} {:?} to xwayland", code.raw() - 8, state); for wl_keyboard in keyboard.client_keyboards(&xstate.client) { - wl_keyboard.key(serial.into(), time, code.raw() - 8, state.into()); + wl_keyboard.key(serial.into(), time.millis(), code.raw() - 8, state.into()); if xstate.last_modifier_state != Some(modifiers) { xstate.last_modifier_state = Some(modifiers); wl_keyboard.modifiers( @@ -478,7 +480,7 @@ impl Common { button: u32, state: ButtonState, serial: Serial, - time: u32, + time: InputTime, ) { if !self.config.cosmic_conf.xwayland_eavesdropping.pointer { return; @@ -518,7 +520,7 @@ impl Common { tracing::trace!("Forwaring ptr button {} {:?} to Xwayland", button, state); for wl_pointer in pointer.client_pointers(&xstate.client) { - wl_pointer.button(serial.into(), time, button, state.into()); + wl_pointer.button(serial.into(), time.millis(), button, state.into()); } } @@ -808,6 +810,7 @@ impl XwmHandler for State { ); } let fullscreen = window.is_fullscreen().then(|| seat.active_output()); + let minimized = window.is_hidden(); let maximized = window.is_maximized(); if let Some(pending) = shell .pending_windows @@ -816,6 +819,7 @@ impl XwmHandler for State { { pending.seat = seat; pending.fullscreen = fullscreen; + pending.minimized = minimized; pending.maximized = maximized; } else { let surface = CosmicSurface::from(window); @@ -823,6 +827,7 @@ impl XwmHandler for State { surface, seat, fullscreen, + minimized, maximized, sticky: false, }) @@ -1042,17 +1047,29 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch() - .unwrap() - .set_grab(self, grab, SERIAL_COUNTER.next_serial()) - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( self, grab, SERIAL_COUNTER.next_serial(), focus, - ) + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + self, + grab, + InputTime::now(), + SERIAL_COUNTER.next_serial(), + focus, + ), } } } @@ -1073,17 +1090,29 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - if grab.is_touch_grab() { - seat.get_touch() - .unwrap() - .set_grab(self, grab, SERIAL_COUNTER.next_serial()) - } else { - seat.get_pointer().unwrap().set_grab( + match grab.grab_type() { + GrabType::Touch => { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } + GrabType::Pointer => seat.get_pointer().unwrap().set_grab( self, grab, SERIAL_COUNTER.next_serial(), focus, - ) + ), + GrabType::TabletTool => seat + .tablet_seat() + .get_tool(grab.tool().unwrap()) + .unwrap() + .set_grab( + self, + grab, + InputTime::now(), + SERIAL_COUNTER.next_serial(), + focus, + ), } } }