diff --git a/Cargo.lock b/Cargo.lock index c27ed2cb..8f2882ec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,15 +21,27 @@ checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" [[package]] name = "accesskit" version = "0.22.0" -source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" dependencies = [ "uuid", ] +[[package]] +name = "accesskit_atspi_common" +version = "0.15.0" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" +dependencies = [ + "accesskit", + "accesskit_consumer", + "atspi-common", + "serde", + "zvariant", +] + [[package]] name = "accesskit_consumer" version = "0.32.0" -source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" dependencies = [ "accesskit", "hashbrown 0.16.1", @@ -38,7 +50,7 @@ dependencies = [ [[package]] name = "accesskit_macos" version = "0.23.0" -source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" dependencies = [ "accesskit", "accesskit_consumer", @@ -48,10 +60,25 @@ dependencies = [ "objc2-foundation 0.2.2", ] +[[package]] +name = "accesskit_unix" +version = "0.18.0" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "atspi", + "futures-lite", + "serde", + "tokio", + "tokio-stream", + "zbus", +] + [[package]] name = "accesskit_windows" version = "0.30.0" -source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" dependencies = [ "accesskit", "accesskit_consumer", @@ -64,10 +91,11 @@ dependencies = [ [[package]] name = "accesskit_winit" version = "0.30.0" -source = "git+https://github.com/wash2/accesskit?rev=6c20249#6c20249d3b9fd45e7002efad9f6b6171a9257912" +source = "git+https://github.com/wash2/accesskit?tag=cosmic-0.14#f0599eed5f18111228266fe3f28991cc48b5964f" dependencies = [ "accesskit", "accesskit_macos", + "accesskit_unix", "accesskit_windows", "raw-window-handle", "winit 0.31.0-beta.2", @@ -135,7 +163,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.13.2", + "bitflags 2.11.0", "cc", "cesu8", "jni", @@ -182,6 +210,15 @@ 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" @@ -227,6 +264,24 @@ dependencies = [ "libloading", ] +[[package]] +name = "ashpd" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2f3f79755c74fd155000314eb349864caa787c6592eace6c6882dad873d9c39" +dependencies = [ + "enumflags2", + "futures-channel", + "futures-util", + "rand 0.9.2", + "raw-window-handle", + "serde", + "serde_repr", + "tokio", + "url", + "zbus", +] + [[package]] name = "ashpd" version = "0.12.3" @@ -236,9 +291,10 @@ dependencies = [ "enumflags2", "futures-channel", "futures-util", - "rand 0.9.5", + "rand 0.9.2", "serde", "serde_repr", + "tokio", "url", "wayland-backend", "wayland-client", @@ -383,6 +439,12 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atomic_float" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "628d228f918ac3b82fe590352cc719d30664a0c13ca3a60266fe02c7132d480a" + [[package]] name = "atomicwrites" version = "0.4.2" @@ -394,10 +456,47 @@ dependencies = [ ] [[package]] -name = "auto_enums" -version = "0.8.8" +name = "atspi" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65398a2893f41bce5c9259f6e1a4f03fbae40637c1bdc755b4f387f48c613b03" +checksum = "c77886257be21c9cd89a4ae7e64860c6f0eefca799bb79127913052bd0eefb3d" +dependencies = [ + "atspi-common", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20c5617155740c98003016429ad13fe43ce7a77b007479350a9f8bf95a29f63d" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-proxies" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2230e48787ed3eb4088996eab66a32ca20c0b67bbd4fd6cdfe79f04f1f04c9fc" +dependencies = [ + "atspi-common", + "serde", + "zbus", +] + +[[package]] +name = "auto_enums" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e4487600931c9a89f8db7ffbdf3fbdd45bb7bd85e26861f659a463cd0dff966" dependencies = [ "derive_utils", "proc-macro2", @@ -470,9 +569,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.2" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" dependencies = [ "serde_core", ] @@ -552,13 +651,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "build_helpers" -version = "0.14.0" -dependencies = [ - "cfg_aliases", -] - [[package]] name = "bumpalo" version = "3.20.2" @@ -610,7 +702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4dbf9978365bac10f54d1d4b04f7ce4427e51f71d61f2fe15e3fed5166474df7" dependencies = [ "async-task", - "bitflags 2.13.2", + "bitflags 2.11.0", "futures-core", "polling", "rustix 1.1.4", @@ -670,6 +762,16 @@ 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" @@ -764,7 +866,7 @@ checksum = "fe6d2e5af09e8c8ad56c969f2157a3d4238cebc7c55f0a517728c38f7b200f81" dependencies = [ "serde", "termcolor", - "unicode-width 0.1.14", + "unicode-width 0.2.2", ] [[package]] @@ -854,7 +956,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "core-foundation 0.10.1", "libc", ] @@ -872,7 +974,7 @@ dependencies = [ name = "cosmic-client-toolkit" version = "0.2.0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cosmic-protocols", "libc", "smithay-client-toolkit", @@ -885,7 +987,7 @@ name = "cosmic-comp" version = "1.0.0" dependencies = [ "anyhow", - "bitflags 2.13.2", + "bitflags 2.11.0", "calloop", "clap_lex", "cosmic-comp-config", @@ -918,7 +1020,6 @@ dependencies = [ "profiling", "rand 0.10.0", "regex", - "resvg 0.45.1", "ron 0.12.0", "rust-embed", "rustix 1.1.4", @@ -929,7 +1030,8 @@ dependencies = [ "smithay", "smithay-egui", "thiserror 2.0.18", - "tiny-skia 0.11.4", + "tiny-skia", + "tokio", "tracing", "tracing-journald", "tracing-subscriber", @@ -971,6 +1073,7 @@ dependencies = [ "notify", "ron 0.12.0", "serde", + "tokio", "tracing", "xdg", "zbus", @@ -1001,7 +1104,7 @@ dependencies = [ name = "cosmic-protocols" version = "0.2.0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -1021,7 +1124,7 @@ dependencies = [ [[package]] name = "cosmic-settings-config" -version = "1.9.0" +version = "0.1.0" dependencies = [ "cosmic-config", "ron 0.11.0", @@ -1040,7 +1143,7 @@ dependencies = [ [[package]] name = "cosmic-settings-daemon-config" -version = "1.9.0" +version = "0.1.0" dependencies = [ "cosmic-config", "cosmic-theme", @@ -1051,7 +1154,7 @@ dependencies = [ name = "cosmic-text" version = "0.19.0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "fontdb", "harfrust", "linebender_resource_handle", @@ -1289,7 +1392,9 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", + "block2 0.6.2", + "libc", "objc2 0.6.4", ] @@ -1317,7 +1422,7 @@ dependencies = [ name = "dnd" version = "0.1.0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "mime 0.1.0", "raw-window-handle", "smithay-client-toolkit", @@ -1355,7 +1460,7 @@ version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80bc8c5c6c2941f70a55c15f8d9f00f9710ebda3ffda98075f996a0e6c92756f" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "drm-ffi", "drm-fourcc", @@ -1365,12 +1470,12 @@ dependencies = [ [[package]] name = "drm-ffi" -version = "0.9.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51a91c9b32ac4e8105dec255e849e0d66e27d7c34d184364fb93e469db08f690" +checksum = "d8e41459d99a9b529845f6d2c909eb9adf3b6d2f82635ae40be8de0601726e8b" dependencies = [ "drm-sys", - "rustix 1.1.4", + "rustix 0.38.44", ] [[package]] @@ -1381,12 +1486,12 @@ checksum = "0aafbcdb8afc29c1a7ee5fbe53b5d62f4565b35a042a662ca9fecd0b54dae6f4" [[package]] name = "drm-sys" -version = "0.8.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8e1361066d91f5ffccff060a3c3be9c3ecde15be2959c1937595f7a82a9f8" +checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c" dependencies = [ "libc", - "linux-raw-sys 0.9.4", + "linux-raw-sys 0.6.5", ] [[package]] @@ -1412,7 +1517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" dependencies = [ "ahash", - "bitflags 2.13.2", + "bitflags 2.11.0", "emath", "epaint", "nohash-hasher", @@ -1936,7 +2041,7 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce852e998d3ca5e4a97014fb31c940dc5ef344ec7d364984525fd11e8a547e6a" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "drm", "drm-fourcc", "gbm-sys", @@ -2104,7 +2209,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b89c83349105e3732062a895becfc71a8f921bb71ecbbdd8ff99263e3b53a0ca" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "gpu-descriptor-types", "hashbrown 0.15.5", ] @@ -2115,7 +2220,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdf242682df893b86f33a73828fb09ca4b2d3bb6cc95249707fc684d27484b91" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", ] [[package]] @@ -2152,7 +2257,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f9f40651a03bc0f7316bd75267ff5767e93017ef3cfffe76c6aa7252cc5a31c" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "core_maths", "read-fonts 0.37.0", @@ -2345,7 +2450,6 @@ dependencies = [ name = "iced" version = "0.14.0" dependencies = [ - "build_helpers", "dnd", "iced_accessibility", "iced_core", @@ -2374,8 +2478,7 @@ dependencies = [ name = "iced_core" version = "0.14.0" dependencies = [ - "bitflags 2.13.2", - "build_helpers", + "bitflags 2.11.0", "bytes", "cosmic-client-toolkit", "dnd", @@ -2412,6 +2515,7 @@ dependencies = [ "iced_core", "log", "rustc-hash 2.1.1", + "tokio", "wasm-bindgen-futures", "wasmtimer", ] @@ -2420,7 +2524,7 @@ dependencies = [ name = "iced_graphics" version = "0.14.0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "cosmic-text", "half", @@ -2459,7 +2563,6 @@ dependencies = [ name = "iced_runtime" version = "0.14.0" dependencies = [ - "build_helpers", "bytes", "cosmic-client-toolkit", "dnd", @@ -2483,15 +2586,14 @@ 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" dependencies = [ - "bitflags 2.13.2", - "build_helpers", + "bitflags 2.11.0", "bytemuck", "cosmic-client-toolkit", "cryoglyph", @@ -2518,7 +2620,6 @@ dependencies = [ name = "iced_widget" version = "0.14.2" dependencies = [ - "build_helpers", "cosmic-client-toolkit", "dnd", "iced_renderer", @@ -2536,7 +2637,6 @@ dependencies = [ name = "iced_winit" version = "0.14.0" dependencies = [ - "build_helpers", "cosmic-client-toolkit", "cursor-icon", "dnd", @@ -2752,7 +2852,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "inotify-sys", "libc", ] @@ -2772,7 +2872,7 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9793345a65d71317763a33066b5d8351f8760dde8d4930fe9e39b5f14a7959d" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "input-sys", "libc", "log", @@ -2930,7 +3030,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fbe853b403ae61a04233030ae8a79d94975281ed9770a1f9e246732b534b28d" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "serde", ] @@ -3034,18 +3134,17 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libcosmic-yoda" version = "0.1.0-yoda.2" dependencies = [ "apply", - "ashpd", + "ashpd 0.12.3", "auto_enums", - "build_helpers", "cosmic-client-toolkit", "cosmic-config", "cosmic-freedesktop-icons", @@ -3072,12 +3171,13 @@ dependencies = [ "log", "palette", "phf 0.13.1", - "roxmltree 0.20.0", + "rfd", "rust-embed", "serde", "slotmap", "taffy", "thiserror 2.0.18", + "tokio", "tracing", "unicode-segmentation", "url", @@ -3090,7 +3190,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59fd96dbb2381ff31f314f07accbdf8550febdcc5cd8761ecaf7c1763361c359" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "libc", "libdisplay-info-derive", "libdisplay-info-sys", @@ -3136,14 +3236,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.25" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "libc", "plain", - "redox_syscall 0.9.4", + "redox_syscall 0.9.0", ] [[package]] @@ -3217,9 +3317,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7" [[package]] name = "linux-raw-sys" @@ -3402,7 +3502,7 @@ version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c7047791b5bc903b8cd963014b355f71dc9864a9a0b727057676c1dcae5cbc15" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block", "core-graphics-types 0.2.0", "foreign-types", @@ -3464,9 +3564,9 @@ checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" [[package]] name = "mio" -version = "1.1.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -3498,7 +3598,7 @@ checksum = "618f667225063219ddfc61251087db8a9aec3c3f0950c916b614e403486f1135" dependencies = [ "arrayvec", "bit-set", - "bitflags 2.13.2", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "codespan-reporting", @@ -3522,7 +3622,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "jni-sys", "log", "ndk-sys", @@ -3552,7 +3652,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cfg-if", "cfg_aliases", "libc", @@ -3580,7 +3680,7 @@ version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "fsevent-sys", "inotify", "kqueue", @@ -3598,7 +3698,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42b8cfee0e339a0337359f3c88165702ac6e600dc01c0cc9579a92d62b08477a" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", ] [[package]] @@ -3763,7 +3863,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -3779,7 +3879,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", + "block2 0.6.2", "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", @@ -3791,7 +3892,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3803,7 +3904,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "objc2 0.6.4", @@ -3815,7 +3916,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "libc", "objc2-core-foundation", ] @@ -3838,7 +3939,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d425caf1df73233f29fd8a5c3e5edbc30d2d4307870f802d18f00d83dc5141a6" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "objc2-core-foundation", "objc2-core-graphics", ] @@ -3855,7 +3956,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.5.1", "libc", "objc2 0.5.2", @@ -3867,7 +3968,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "objc2 0.6.4", "objc2-core-foundation", @@ -3879,7 +3980,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3891,7 +3992,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.5.1", "objc2 0.5.2", "objc2-foundation 0.2.2", @@ -3904,7 +4005,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "objc2 0.6.4", "objc2-core-foundation", "objc2-foundation 0.3.2", @@ -4008,7 +4109,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ - "approx", + "approx 0.5.1", "fast-srgb8", "palette_derive", "phf 0.11.3", @@ -4255,7 +4356,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "crc32fast", "fdeflate", "flate2", @@ -4276,6 +4377,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + [[package]] name = "portable-atomic" version = "1.13.1" @@ -4426,6 +4533,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", + "serde", ] [[package]] @@ -4456,9 +4564,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.5" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.5", @@ -4570,7 +4678,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c5018d583d6d2f5499352aea8d177e9067d1eb03ab17c78169d5ba7a30001b15" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "libredox", ] @@ -4580,16 +4688,16 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", ] [[package]] name = "redox_syscall" -version = "0.9.4" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "737970939a87c6fa31e7acad13307bccbb017a073b695b6089a2c484f929e20e" +checksum = "c5102a6aaa05aa011a238e178e6bca86d2cb56fc9f586d37cb80f5bca6e07759" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", ] [[package]] @@ -4654,9 +4762,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reis" -version = "0.7.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b967ec6489a42067a20724f11987bb96178ea796873cbe1afd25fb93ee6f85f" +checksum = "81f3fedd2777cde52c1be5e572efbec485eac7b801c47820eda388d4f13b9c4b" dependencies = [ "calloop", "enumflags2", @@ -4680,7 +4788,7 @@ dependencies = [ "pico-args", "rgb", "svgtypes 0.13.0", - "tiny-skia 0.11.4", + "tiny-skia", "usvg 0.37.0", ] @@ -4696,11 +4804,35 @@ dependencies = [ "pico-args", "rgb", "svgtypes 0.15.3", - "tiny-skia 0.11.4", + "tiny-skia", "usvg 0.45.1", "zune-jpeg 0.4.21", ] +[[package]] +name = "rfd" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15ad77d9e70a92437d8f74c35d99b4e4691128df018833e99f90bcd36152672" +dependencies = [ + "ashpd 0.11.1", + "block2 0.6.2", + "dispatch2", + "js-sys", + "log", + "objc2 0.6.4", + "objc2-app-kit 0.3.2", + "objc2-core-foundation", + "objc2-foundation 0.3.2", + "pollster", + "raw-window-handle", + "urlencoding", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-sys 0.60.2", +] + [[package]] name = "rgb" version = "0.8.52" @@ -4717,7 +4849,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db09040cc89e461f1a265139777a2bde7f8d8c67c4936f700c63ce3e2904d468" dependencies = [ "base64 0.22.1", - "bitflags 2.13.2", + "bitflags 2.11.0", "serde", "serde_derive", "unicode-ident", @@ -4729,7 +4861,7 @@ version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "once_cell", "serde", "serde_derive", @@ -4807,7 +4939,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -4820,7 +4952,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -4839,7 +4971,7 @@ version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd3c7c96f8a08ee34eff8857b11b49b07d71d1c3f4e88f8a88d4c9e9f90b1702" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "core_maths", "log", @@ -4907,15 +5039,15 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.11.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2a4360b9abcdcee43809e6fc11d6d61ca5d25734026a8fc46c2883eea3f13f" +checksum = "1dd3accc0f3f4bbaf2c9e1957a030dc582028130c67660d44c0a0345a22ca69b" dependencies = [ "ab_glyph", "log", "memmap2 0.9.10", "smithay-client-toolkit", - "tiny-skia 0.12.0", + "tiny-skia", ] [[package]] @@ -5132,12 +5264,13 @@ checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "smithay" version = "0.7.0" -source = "git+https://github.com/smithay/smithay.git?rev=e3d461a#e3d461a057ba244d213a8498ec372b0799cca103" +source = "git+https://github.com/smithay/smithay.git?rev=1ed69cb#1ed69cb55e9d0e9f38887c3b7d53d24365c4b14f" dependencies = [ "aliasable", "appendlist", "ash", - "bitflags 2.13.2", + "atomic_float", + "bitflags 2.11.0", "calloop", "cc", "cursor-icon", @@ -5145,7 +5278,6 @@ dependencies = [ "drm", "drm-ffi", "drm-fourcc", - "drm-sys", "encoding_rs", "errno", "gbm", @@ -5159,9 +5291,8 @@ dependencies = [ "libseat", "pixman", "pkg-config", - "portable-atomic", "profiling", - "rand 0.10.0", + "rand 0.9.2", "reis", "rustix 1.1.4", "scopeguard", @@ -5190,7 +5321,7 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0512da38f5e2b31201a93524adb8d3136276fa4fe4aafab4e1f727a82b534cc0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "calloop", "calloop-wayland-source", @@ -5227,13 +5358,16 @@ dependencies = [ [[package]] name = "smithay-egui" version = "0.2.0" -source = "git+https://github.com/Smithay/smithay-egui.git?rev=6511552#65115521c756f356a7bcac8f1eeb715817a4666f" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6794c95b83518f9f91ae8c2faee52302d521c0d541d016b4ed632374041d9c42" dependencies = [ + "cgmath", "egui", "egui_extras", "egui_glow", "image", "log", + "memoffset", "smithay", "xkbcommon 0.8.0", ] @@ -5254,6 +5388,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27207bb65232eda1f588cf46db2fee75c0808d557f6b3cf19a75f5d6d7c94df1" +[[package]] +name = "socket2" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "softbuffer" version = "0.4.1" @@ -5266,11 +5410,11 @@ dependencies = [ "fastrand", "foreign-types", "js-sys", - "libredox", "log", "memmap2 0.9.10", "objc", "raw-window-handle", + "redox_syscall 0.5.18", "rustix 0.38.44", "tiny-xlib", "wasm-bindgen", @@ -5288,7 +5432,7 @@ 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.2", + "bitflags 2.11.0", ] [[package]] @@ -5537,21 +5681,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]] @@ -5565,17 +5695,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" @@ -5615,6 +5734,45 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "tokio" +version = "1.52.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "tracing", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "toml" version = "0.5.11" @@ -5941,6 +6099,12 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "usvg" version = "0.37.0" @@ -5975,7 +6139,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", @@ -6009,7 +6173,7 @@ dependencies = [ "rctree", "strict-num", "svgtypes 0.13.0", - "tiny-skia-path 0.11.4", + "tiny-skia-path", ] [[package]] @@ -6168,7 +6332,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap 2.13.0", "semver", @@ -6208,7 +6372,7 @@ version = "0.31.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "645c7c96bb74690c3189b5c9cb4ca1627062bb23693a4fad9d8c3de958260144" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "rustix 1.1.4", "wayland-backend", "wayland-scanner", @@ -6220,7 +6384,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cursor-icon", "wayland-backend", ] @@ -6248,11 +6412,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.13" +version = "0.32.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" +checksum = "563a85523cade2429938e790815fd7319062103b9f4a2dc806e9b53b95982d8f" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -6265,7 +6429,7 @@ version = "20250721.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40a1f863128dcaaec790d7b4b396cc9b9a7a079e878e18c47e6c2d2c5a8dcbb1" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6278,7 +6442,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e9567599ef23e09b8dad6e429e5738d4509dfc46b3b21f32841a304d16b29c8" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6292,7 +6456,7 @@ version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa98634619300a535a9a97f338aed9a5ff1e01a461943e8346ff4ae26007306b" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6305,7 +6469,7 @@ version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -6330,7 +6494,7 @@ version = "0.31.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc1846eb04c49182e04f4a099e2a830a2b745610bbc1d61246e206f29c7000a0" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "downcast-rs", "rustix 1.1.4", "wayland-backend", @@ -6382,7 +6546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9cb534d5ffd109c7d1135f34cdae29e60eab94855a625dcfe1705f8bc7ad79f" dependencies = [ "arrayvec", - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "cfg-if", "cfg_aliases", @@ -6414,7 +6578,7 @@ dependencies = [ "arrayvec", "bit-set", "bit-vec", - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "cfg_aliases", "document-features", @@ -6474,7 +6638,7 @@ dependencies = [ "arrayvec", "ash", "bit-set", - "bitflags 2.13.2", + "bitflags 2.11.0", "block", "bytemuck", "cfg-if", @@ -6518,7 +6682,7 @@ version = "28.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e18308757e594ed2cd27dddbb16a139c42a683819d32a2e0b1b0167552f5840c" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "js-sys", "log", @@ -7069,7 +7233,7 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" name = "winit" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cfg_aliases", "cursor-icon", "dpi 0.1.2", @@ -7095,7 +7259,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2879d2854d1a43e48f67322d4bd097afcb6eb8f8f775c8de0260a71aea1df1aa" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cfg_aliases", "cursor-icon", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7121,7 +7285,7 @@ name = "winit-android" version = "0.31.0-beta.2" dependencies = [ "android-activity", - "bitflags 2.13.2", + "bitflags 2.11.0", "dpi 0.1.2", "ndk", "raw-window-handle", @@ -7137,7 +7301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d9c0d2cd93efec3a9f9ad819cfaf0834782403af7c0d248c784ec0c61761df" dependencies = [ "android-activity", - "bitflags 2.13.2", + "bitflags 2.11.0", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "ndk", "raw-window-handle", @@ -7150,7 +7314,7 @@ dependencies = [ name = "winit-appkit" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "dpi 0.1.2", @@ -7173,7 +7337,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21310ca07851a49c348e0c2cc768e36b52ca65afda2c2354d78ed4b90074d8aa" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7223,7 +7387,7 @@ dependencies = [ name = "winit-core" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cursor-icon", "dpi 0.1.2", "keyboard-types", @@ -7238,7 +7402,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4f0ccd7abb43740e2c6124ac7cae7d865ecec74eec63783e8922577ac232583" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cursor-icon", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "keyboard-types", @@ -7251,7 +7415,7 @@ dependencies = [ name = "winit-orbital" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "dpi 0.1.2", "libredox", "orbclient", @@ -7268,7 +7432,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51ea1fb262e7209f265f12bd0cc792c399b14355675e65531e9c8a87db287d46" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "orbclient", "raw-window-handle", @@ -7282,7 +7446,7 @@ dependencies = [ name = "winit-uikit" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "dpi 0.1.2", @@ -7303,7 +7467,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680a356e798837d8eb274d4556e83bceaf81698194e31aafc5cfb8a9f2fab643" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "block2 0.6.2", "dispatch2", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7323,7 +7487,7 @@ name = "winit-wayland" version = "0.31.0-beta.2" dependencies = [ "ahash", - "bitflags 2.13.2", + "bitflags 2.11.0", "calloop", "cursor-icon", "dpi 0.1.2", @@ -7350,7 +7514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ce5afb2ba07da603f84b722c95f9f9396d2cedae3944fb6c0cda4a6f88de545" dependencies = [ "ahash", - "bitflags 2.13.2", + "bitflags 2.11.0", "calloop", "cursor-icon", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7374,7 +7538,7 @@ name = "winit-web" version = "0.31.0-beta.2" dependencies = [ "atomic-waker", - "bitflags 2.13.2", + "bitflags 2.11.0", "concurrent-queue", "cursor-icon", "dpi 0.1.2", @@ -7397,7 +7561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c2490a953fb776fbbd5e295d54f1c3847f4f15b6c3929ec53c09acda6487a92" dependencies = [ "atomic-waker", - "bitflags 2.13.2", + "bitflags 2.11.0", "concurrent-queue", "cursor-icon", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7417,7 +7581,7 @@ dependencies = [ name = "winit-win32" version = "0.31.0-beta.2" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cursor-icon", "dpi 0.1.2", "raw-window-handle", @@ -7434,7 +7598,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644ea78af0e858aa3b092e5d1c67c41995a98220c81813f1353b28bc8bb91eaa" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "cursor-icon", "dpi 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "raw-window-handle", @@ -7451,7 +7615,7 @@ version = "0.31.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa5b600756534c7041aa93cd0d244d44b09fca1b89e202bd1cd80dd9f3636c46" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "bytemuck", "calloop", "cursor-icon", @@ -7554,7 +7718,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.13.2", + "bitflags 2.11.0", "indexmap 2.13.0", "log", "serde", @@ -7625,9 +7789,9 @@ checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" [[package]] name = "xcursor" -version = "0.3.11" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163b33ed8786455e2fa5d72f554057ce3f3182425434f756cd39c99839d88e23" +checksum = "bec9e4a500ca8864c5b47b8b482a73d62e4237670e5b5f1d6b9e3cae50f28f2b" [[package]] name = "xdg" @@ -7684,7 +7848,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.13.2", + "bitflags 2.11.0", "dlib", "log", "once_cell", @@ -7772,6 +7936,7 @@ dependencies = [ "rustix 1.1.4", "serde", "serde_repr", + "tokio", "tracing", "uds_windows", "uuid", @@ -7782,6 +7947,30 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zbus-lockstep" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6998de05217a084b7578728a9443d04ea4cd80f2a0839b8d78770b76ccd45863" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10da05367f3a7b7553c8cdf8fa91aee6b64afebe32b51c95177957efc47ca3a0" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + [[package]] name = "zbus_macros" version = "5.16.0" @@ -7808,6 +7997,18 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zbus_xml" +version = "5.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8067892e940ed1727dea64690378601603b31d62dfde019a5335fbb7c0e0ed9" +dependencies = [ + "quick-xml", + "serde", + "zbus_names", + "zvariant", +] + [[package]] name = "zeno" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index 11001e83..fddb41b9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,6 +44,7 @@ iced_graphics = { path = "../libcosmic/iced/graphics", features = ["geometry"] } indexmap = "2.13" keyframe = "1.1.1" cosmic = { package = "libcosmic-yoda", path = "../libcosmic", default-features = false, features = [ + "tokio", "wayland", "multi-window", ] } @@ -52,7 +53,6 @@ log-panics = { version = "2", features = ["with-backtrace"] } ordered-float = "5.1" png = "0.18" regex = "1" -resvg = "0.45" ron = "0.12" rust-embed = { version = "8.11", features = ["debug-embed"] } sanitize-filename = "0.6.0" @@ -78,6 +78,7 @@ xdg = "^3.0" xdg-user = "0.2.1" xkbcommon = "0.9" zbus = "5.14.0" +tokio = { version = "1", features = ["rt-multi-thread"] } profiling = { version = "1.0" } rustix = { version = "1.1.4", features = ["process"] } rand = "0.10" @@ -101,7 +102,6 @@ features = [ "backend_drm", "backend_gbm", "backend_egl", - "backend_libei", "backend_libinput", "backend_session_libseat", "backend_udev", @@ -177,5 +177,4 @@ dnd = { path = "../window_clipboard/dnd" } mime = { path = "../window_clipboard/mime" } [patch.crates-io] -smithay = { git = "https://github.com/smithay/smithay.git", rev = "e3d461a" } -smithay-egui = { git = "https://github.com/Smithay/smithay-egui.git", rev = "6511552" } +smithay = { git = "https://github.com/smithay/smithay.git", rev = "1ed69cb" } diff --git a/cosmic-comp-config/src/lib.rs b/cosmic-comp-config/src/lib.rs index 510927f9..e5e73883 100644 --- a/cosmic-comp-config/src/lib.rs +++ b/cosmic-comp-config/src/lib.rs @@ -66,13 +66,6 @@ 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 { @@ -108,10 +101,7 @@ pub struct CosmicCompConfig { pub appearance_settings: AppearanceConfig, /// Hide the cursor after this many seconds of pointer inactivity (None disables) pub cursor_hide_timeout: Option, - /// 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 { @@ -149,9 +139,7 @@ impl Default for CosmicCompConfig { accessibility_zoom: ZoomConfig::default(), appearance_settings: AppearanceConfig::default(), cursor_hide_timeout: None, - cursor_shake_to_find: true, activation_policy: ActivationPolicy::default(), - decoration_preference: DecorationPreference::default(), } } } @@ -207,10 +195,6 @@ pub struct ZoomConfig { pub enable_mouse_zoom_shortcuts: bool, } -impl ZoomConfig { - pub const ZOOM_INCREMENT_PRESETS: &[u32] = &[10, 25, 50, 75, 100, 150, 200]; -} - impl Default for ZoomConfig { fn default() -> Self { ZoomConfig { diff --git a/resources/i18n/da/cosmic_comp.ftl b/resources/i18n/da/cosmic_comp.ftl index ad4befea..e69de29b 100644 --- a/resources/i18n/da/cosmic_comp.ftl +++ b/resources/i18n/da/cosmic_comp.ftl @@ -1,28 +0,0 @@ -a11y-zoom-move-continuously = Visningen bevæger sig kontinuerligt med markøren -a11y-zoom-move-onedge = Vis bevægelser når markør rammer kant -a11y-zoom-move-centered = Vis bevægelser, for at holde markør centreret -a11y-zoom-settings = Forstørrelsesglas-indstillinger... -grow-window = Gro -shrink-window = Skrump -swap-windows = Byt Vinduer -stack-windows = Stabel Vinduer -window-menu-tiled = Gør vindue flydende -window-menu-screenshot = Tag skærmbillede -window-menu-move = Flyt -window-menu-resize = Skift størrelse -window-menu-move-prev-workspace = Flyt til forrige arbejdsområde -window-menu-move-next-workspace = Flyt til næste arbejdsområde -window-menu-stack = Opret vinduestak -window-menu-unstack-all = Udtag vinduer af stak -window-menu-unstack = Udtag vindue af stak -window-menu-sticky = Fastgjort vindue -window-menu-close = Luk -window-menu-close-all = Luk alle vinduer -window-menu-resize-edge-top = Top -window-menu-resize-edge-left = Venstre -window-menu-resize-edge-right = Højre -window-menu-resize-edge-bottom = Bund -window-menu-minimize = Minimér -window-menu-maximize = Maksimér -window-menu-fullscreen = Fuld skærm -unknown-keybinding = diff --git a/resources/i18n/en-GB/cosmic_comp.ftl b/resources/i18n/en-GB/cosmic_comp.ftl index 853cc97d..e69de29b 100644 --- a/resources/i18n/en-GB/cosmic_comp.ftl +++ b/resources/i18n/en-GB/cosmic_comp.ftl @@ -1,28 +0,0 @@ -a11y-zoom-move-continuously = View moves continuously with pointer -a11y-zoom-move-onedge = View moves when pointer reaches edge -a11y-zoom-move-centered = View moves to keep pointer centred -a11y-zoom-settings = Magnifier settings... -grow-window = Grow -shrink-window = Shrink -swap-windows = Swap Windows -stack-windows = Stack Windows -unknown-keybinding = -window-menu-minimize = Minimise -window-menu-maximize = Maximise -window-menu-fullscreen = Fullscreen -window-menu-tiled = Float window -window-menu-screenshot = Take screenshot -window-menu-move = Move -window-menu-resize = Resize -window-menu-move-prev-workspace = Move to previous workspace -window-menu-move-next-workspace = Move to next workspace -window-menu-stack = Create window stack -window-menu-unstack-all = Unstack windows -window-menu-unstack = Unstack window -window-menu-sticky = Sticky window -window-menu-close = Close -window-menu-close-all = Close all windows -window-menu-resize-edge-top = Top -window-menu-resize-edge-left = Left -window-menu-resize-edge-right = Right -window-menu-resize-edge-bottom = Bottom diff --git a/resources/i18n/fil/cosmic_comp.ftl b/resources/i18n/fil/cosmic_comp.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/resources/i18n/gl/cosmic_comp.ftl b/resources/i18n/gl/cosmic_comp.ftl deleted file mode 100644 index 1176cad6..00000000 --- a/resources/i18n/gl/cosmic_comp.ftl +++ /dev/null @@ -1,28 +0,0 @@ -a11y-zoom-move-continuously = A vista móvese continuamente co punteiro -a11y-zoom-move-onedge = A vista móvese cando o punteiro chega ao bordo -a11y-zoom-move-centered = Mover a vista para manter o cursor centrado -a11y-zoom-settings = Configuración da lupa... -grow-window = Aumentar -shrink-window = Encoller -swap-windows = Cambiar xanelas -stack-windows = Apilar xanelas -unknown-keybinding = -window-menu-minimize = Minimizar -window-menu-maximize = Maximizar -window-menu-fullscreen = Pantalla Completa -window-menu-tiled = Xanela flotante -window-menu-screenshot = Capturar pantalla -window-menu-move = Mover -window-menu-resize = Redimensionar -window-menu-move-prev-workspace = Mover ao espazo de traballo anterior -window-menu-move-next-workspace = Mover ao seguinte espazo de traballo -window-menu-stack = Crear pila de xanelas -window-menu-unstack-all = Desapilar xanelas -window-menu-unstack = Desapilar xanela -window-menu-sticky = Xanela persistente -window-menu-close = Pechar -window-menu-close-all = Pechar todas as xanelas -window-menu-resize-edge-top = Arriba -window-menu-resize-edge-left = Esquerda -window-menu-resize-edge-right = Dereita -window-menu-resize-edge-bottom = Fondo diff --git a/resources/i18n/it/cosmic_comp.ftl b/resources/i18n/it/cosmic_comp.ftl index b1eb56c3..ba92609f 100644 --- a/resources/i18n/it/cosmic_comp.ftl +++ b/resources/i18n/it/cosmic_comp.ftl @@ -1,4 +1,4 @@ -grow-window = Crescere +grow-window = Ingrandisci shrink-window = Riduci swap-windows = Scambia le finestre stack-windows = Sovrapponi le finestre @@ -6,7 +6,7 @@ unknown-keybinding = window-menu-minimize = Minimizza window-menu-maximize = Massimizza window-menu-tiled = Finestra flottante -window-menu-screenshot = Scatta uno screenshot +window-menu-screenshot = Cattura una schermata window-menu-move = Sposta window-menu-resize = Ridimensiona window-menu-move-prev-workspace = Sposta all'area di lavoro precedente @@ -22,7 +22,7 @@ window-menu-resize-edge-left = Sinistra window-menu-resize-edge-right = Destra window-menu-resize-edge-bottom = In basso window-menu-fullscreen = Schermo intero -a11y-zoom-settings = Impostazioni lente d'ingrandimento... +a11y-zoom-settings = Opzioni lente d'ingrandimento... a11y-zoom-move-continuously = Segue sempre il cursorse a11y-zoom-move-centered = Mantiene il cursore centrato a11y-zoom-move-onedge = Segue il cursore ai bordi diff --git a/resources/i18n/oc/cosmic_comp.ftl b/resources/i18n/oc/cosmic_comp.ftl index a1238332..e69de29b 100644 --- a/resources/i18n/oc/cosmic_comp.ftl +++ b/resources/i18n/oc/cosmic_comp.ftl @@ -1,20 +0,0 @@ -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/resources/i18n/sat/cosmic_comp.ftl b/resources/i18n/sat/cosmic_comp.ftl deleted file mode 100644 index e69de29b..00000000 diff --git a/src/backend/kms/device.rs b/src/backend/kms/device.rs index c58450bc..bb32f5a3 100644 --- a/src/backend/kms/device.rs +++ b/src/backend/kms/device.rs @@ -59,7 +59,7 @@ use std::{ time::Duration, }; -use super::{drm_helpers, surface::Surface}; +use super::{drm_helpers, socket::Socket, surface::Surface}; #[derive(Debug)] pub struct EGLInternals { @@ -98,12 +98,14 @@ pub struct Device { pub texture_formats: FormatSet, event_token: Option, + pub socket: Option, } #[derive(Debug)] struct ReusableDevice { leasing_global: Option, active_clients: HashSet, + socket: Option, } #[derive(Debug)] @@ -591,7 +593,7 @@ impl State { } } - pub fn device_removed(&mut self, dev: dev_t, _dh: &DisplayHandle) -> Result<()> { + pub fn device_removed(&mut self, dev: dev_t, dh: &DisplayHandle) -> Result<()> { let backend = self.backend.kms(); // we can't use DrmNode::from_node_id, because that assumes the node is still on sysfs let drm_node = backend @@ -614,6 +616,13 @@ impl State { if let Some(token) = device.event_token.take() { self.common.event_loop_handle.remove(token); } + if let Some(socket) = device.socket.take() { + self.common.event_loop_handle.remove(socket.token); + self.common + .dmabuf_state + .destroy_global::(dh, socket.dmabuf_global); + dh.remove_global::(socket.drm_global); + } backend.api.as_mut().remove_node(&device.inner.render_node); backend .primary_node @@ -693,7 +702,7 @@ impl Device { ) .with_context(|| { format!( - "Failed to obtain file descriptor for drm device: {}", + "Failed to optain file descriptor for drm device: {}", path.display() ) })?, @@ -746,7 +755,23 @@ impl Device { let ReusableDevice { leasing_global, active_clients, + socket, } = reuse.unwrap_or_else(|| { + let socket = match (!is_software) + .then(|| common.create_socket(dh, render_node, texture_formats.clone())) + .transpose() + { + Ok(socket) => socket, + Err(err) => { + warn!( + ?err, + "Failed to initialize hardware-acceleration for clients on {}.", + render_node, + ); + None + } + }; + let leasing_global = match (!is_software) .then(|| DrmLeaseState::new::(dh, &dev_node)) .transpose() @@ -765,6 +790,7 @@ impl Device { ReusableDevice { leasing_global, active_clients: HashSet::new(), + socket, } }); @@ -805,6 +831,7 @@ impl Device { texture_formats, event_token: Some(token), + socket, }) } @@ -865,6 +892,7 @@ impl Device { let device = ReusableDevice { leasing_global: self.inner.leasing_global, active_clients: self.inner.active_clients, + socket: self.socket, }; let state = OldDeviceState { @@ -1241,15 +1269,26 @@ fn populate_modes( ) -> Result<()> { let conn_info = drm.get_connector(conn, false)?; let max_bpc = drm_helpers::get_max_bpc(drm, conn)?.map(|(_val, range)| range.end.min(16)); - let Some(mode) = conn_info + let preferred = conn_info .modes() .iter() .find(|mode| mode.mode_type().contains(ModeTypeFlags::PREFERRED)) .copied() - .or(conn_info.modes().first().copied()) - else { + .or(conn_info.modes().first().copied()); + let Some(preferred) = preferred else { anyhow::bail!("No mode found"); }; + // Prefer the highest refresh rate at the native resolution so that + // high-refresh panels (120 Hz, 144 Hz, …) are used out-of-the-box + // without a pre-existing outputs.ron config. + let preferred_size = preferred.size(); + let mode = conn_info + .modes() + .iter() + .filter(|m| m.size() == preferred_size) + .max_by_key(|m| drm_helpers::calculate_refresh_rate(**m)) + .copied() + .unwrap_or(preferred); let refresh_rate = drm_helpers::calculate_refresh_rate(mode); let output_mode = OutputMode { diff --git a/src/backend/kms/drm_helpers.rs b/src/backend/kms/drm_helpers.rs index 46659613..8629c9d7 100644 --- a/src/backend/kms/drm_helpers.rs +++ b/src/backend/kms/drm_helpers.rs @@ -75,7 +75,6 @@ pub fn display_configuration( // And then cleanup if device.is_atomic() { let mut req = AtomicModeReq::new(); - let mut has_changes = false; let plane_handles = device.plane_handles()?; // We cannot just shortcut and use the legacy api for all cleanups because of this. @@ -96,15 +95,10 @@ pub fn display_configuration( let fb_id = get_prop(device, plane, "FB_ID")?; req.add_property(plane, crtc_id, property::Value::CRTC(None)); req.add_property(plane, fb_id, property::Value::Framebuffer(None)); - has_changes = true; } } } - // Skip an empty commit: a no-op modeset that also fails with EPERM - // without DRM master (e.g. a render-only secondary GPU). - if has_changes { - device.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, req)?; - } + device.atomic_commit(AtomicCommitFlags::ALLOW_MODESET, req)?; } else { for crtc in res_handles.crtcs() { #[allow(deprecated)] diff --git a/src/backend/kms/mod.rs b/src/backend/kms/mod.rs index 36c6407c..16559e4e 100644 --- a/src/backend/kms/mod.rs +++ b/src/backend/kms/mod.rs @@ -4,15 +4,12 @@ use crate::{ config::{CompOutputConfig, ScreenFilter}, shell::Shell, state::BackendData, - utils::{env::dev_var, global::remove_global_with_timer, prelude::*}, - wayland::protocols::{drm::WlDrmState, output_power::OutputPowerState}, + utils::{env::dev_var, prelude::*}, + wayland::protocols::output_power::OutputPowerState, }; -use anyhow::{self, Context, Result}; -use calloop::{ - LoopSignal, - timer::{TimeoutAction, Timer}, -}; +use anyhow::{Context, Result}; +use calloop::LoopSignal; use cosmic_comp_config::output::comp::{AdaptiveSync, OutputState}; use indexmap::IndexMap; use render::gles::GbmGlowBackend; @@ -32,19 +29,14 @@ use smithay::{ calloop::{Dispatcher, EventLoop, LoopHandle}, drm::{ Device as _, - control::{ - Device as _, - connector::{Interface, State as ConnectorState}, - crtc, - }, + control::{Device as _, connector::Interface, crtc}, }, input::{self, Libinput}, - wayland_protocols::wp::linux_dmabuf::zv1::server::zwp_linux_dmabuf_feedback_v1::TrancheFlags, wayland_server::{Client, DisplayHandle}, }, utils::{Clock, DevPath, Monotonic, Size}, wayland::{ - dmabuf::{DmabufFeedbackBuilder, DmabufGlobal}, + dmabuf::DmabufGlobal, drm_syncobj::{DrmSyncobjState, supports_syncobj_eventfd}, relative_pointer::RelativePointerManagerState, }, @@ -56,12 +48,12 @@ use std::{ collections::{HashMap, HashSet}, path::Path, sync::{Arc, RwLock, atomic::AtomicBool}, - time::Duration, }; mod device; mod drm_helpers; pub mod render; +mod socket; mod surface; use device::*; pub(crate) use surface::Surface; @@ -82,7 +74,6 @@ pub struct KmsState { libinput: Libinput, pub syncobj_state: Option, - pub dmabuf_global: Option, } pub struct KmsGuard<'a> { @@ -140,7 +131,6 @@ pub fn init_backend( libinput: libinput_context, syncobj_state: None, - dmabuf_global: None, }); // manually add already present gpus @@ -152,10 +142,9 @@ pub fn init_backend( } } - if let Err(err) = state.select_primary_gpu(dh) { + if let Err(err) = state.backend.kms().select_primary_gpu(dh) { warn!("Failed to determine primary gpu: {}", err); } - state.update_default_feedback(); if let Err(err) = state.refresh_output_config() { info!( @@ -215,7 +204,7 @@ fn init_libinput( state.backend.kms().input_devices.remove(&*device.name()); } - state.process_input_event(event, crate::input::InputBackendId::Normal); + state.process_input_event(event); for output in state.common.shell.read().outputs() { state.backend.kms().schedule_render(output); @@ -254,18 +243,13 @@ fn determine_primary_gpu( // try to find builtin display for dev in drm_devices.values() { - 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) + 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 + } }) { return Ok(Some(dev.inner.render_node)); } @@ -333,13 +317,11 @@ fn init_udev( { let backend = state.backend.kms(); - if matches!(event, UdevEvent::Added { .. } | UdevEvent::Removed { .. }) { - if backend.primary_node.read().unwrap().is_none() - && let Err(err) = state.select_primary_gpu(&dh) - { - warn!("Failed to determine a new primary gpu: {}", err); - } - state.update_default_feedback(); + if matches!(event, UdevEvent::Added { .. } | UdevEvent::Removed { .. }) + && backend.primary_node.read().unwrap().is_none() + && let Err(err) = state.backend.kms().select_primary_gpu(&dh) + { + warn!("Failed to determine a new primary gpu: {}", err); } } @@ -483,118 +465,50 @@ impl State { device.drm.pause(); } } +} +impl KmsState { fn select_primary_gpu(&mut self, dh: &DisplayHandle) -> Result<()> { // We don't have to check the allow/blocklist here, // as any disallowed devices won't be in `self.drm_devices`. - let kms = self.backend.kms(); - let mut primary_node = kms.primary_node.write().unwrap(); + let mut primary_node = self.primary_node.write().unwrap(); let _ = primary_node.take(); // if we error don't leave an old node in place - *primary_node = determine_primary_gpu(&kms.drm_devices, kms.session.seat())?; + *primary_node = determine_primary_gpu(&self.drm_devices, self.session.seat())?; if let Some(node) = *primary_node { info!("Using {} as primary gpu for rendering.", node); - kms.software_renderer.take(); - - // setup minimal feedback. We will update it in `update_default_feedback` - let primary_formats = kms - .drm_devices - .values() - .find(|dev| dev.inner.render_node == node) - .unwrap() - .texture_formats - .clone(); - let feedback = DmabufFeedbackBuilder::new(node.dev_id(), primary_formats.clone()) - .build() - .unwrap(); - - if let Some(global) = kms.dmabuf_global.as_ref() { - self.common - .dmabuf_state - .set_default_feedback(global, &feedback); - } else { - let dmabuf_global = self - .common - .dmabuf_state - .create_global_with_default_feedback::(dh, &feedback); - kms.dmabuf_global = Some(dmabuf_global); - }; - - let device_path = node - .dev_path_with_type(NodeType::Render) - .or_else(|| node.dev_path()) - .ok_or(anyhow::anyhow!( - "Could not determine path for gpu node: {}", - node - ))?; - - if let Some(drm) = self.common.wl_drm_state.as_mut() { - drm.update_device(device_path, primary_formats); - } else { - self.common.wl_drm_state = Some(WlDrmState::new::( - dh, - device_path, - primary_formats, - kms.dmabuf_global.as_ref().unwrap(), - )); - } - } else if kms.software_renderer.is_none() { + self.software_renderer.take(); + } else if self.software_renderer.is_none() { info!("Failed to find a suitable gpu, using software renderingr"); - kms.software_renderer = match software_renderer() { + self.software_renderer = match software_renderer() { Ok(renderer) => Some(renderer), Err(err) => { error!(?err, "Failed to initialize software EGL renderer."); None } }; - - if let Some(drm) = self.common.wl_drm_state.take() { - remove_global_with_timer(dh, &self.common.event_loop_handle, drm.global().clone()); - } - if let Some(global) = kms.dmabuf_global.take() { - self.common - .dmabuf_state - .disable_global::(dh, &global); - let source = Timer::from_duration(Duration::from_secs(5)); - let res = - self.common - .event_loop_handle - .insert_source(source, move |_, _, state| { - state - .common - .dmabuf_state - .destroy_global::(&state.common.display_handle, global); - TimeoutAction::Drop - }); - if let Err(err) = res { - tracing::error!( - "failed to insert timer source to destroy output global: {}", - err - ); - } - } } if !crate::utils::env::bool_var("COSMIC_DISABLE_SYNCOBJ").unwrap_or(false) { if let Some(primary_node) = primary_node .as_ref() .and_then(|node| node.node_with_type(NodeType::Primary).and_then(|x| x.ok())) - && let Some(device) = kms.drm_devices.get(&primary_node) + && let Some(device) = self.drm_devices.get(&primary_node) { let import_device = device.drm.device().device_fd().clone(); if supports_syncobj_eventfd(&import_device) { - if let Some(state) = kms.syncobj_state.as_mut() { + if let Some(state) = self.syncobj_state.as_mut() { state.update_device(import_device); } else { let syncobj_state = DrmSyncobjState::new::(dh, import_device); - kms.syncobj_state = Some(syncobj_state); + self.syncobj_state = Some(syncobj_state); } return Ok(()); } } - if let Some(old_state) = kms.syncobj_state.take() { + if let Some(old_state) = self.syncobj_state.take() { dh.remove_global::(old_state.into_global()); } } @@ -602,45 +516,6 @@ impl State { Ok(()) } - fn update_default_feedback(&mut self) { - let kms = self.backend.kms(); - let primary_node = kms.primary_node.read().unwrap(); - if let Some(primary_node) = *primary_node { - let primary_formats = kms - .drm_devices - .values() - .find(|dev| dev.inner.render_node == primary_node) - .unwrap() - .texture_formats - .clone(); - - let mut feedback = - DmabufFeedbackBuilder::new(primary_node.dev_id(), primary_formats.clone()); - for dev in kms - .drm_devices - .values() - .filter(|dev| dev.inner.render_node != primary_node) - { - feedback = feedback.add_preference_tranche( - dev.inner.render_node.dev_id(), - TrancheFlags::Sampling, - dev.texture_formats.iter().cloned(), - 6..=6, - ); - } - - let default_feedback = feedback.build().unwrap(); - self.common.dmabuf_state.set_default_feedback( - kms.dmabuf_global - .as_ref() - .expect("Primary node but no dmabuf global?"), - &default_feedback, - ); - } - } -} - -impl KmsState { pub fn switch_vt(&mut self, num: i32) -> Result<(), anyhow::Error> { self.session.change_vt(num).map_err(Into::into) } @@ -648,25 +523,29 @@ impl KmsState { pub fn dmabuf_imported( &mut self, client: Option, - _global: &DmabufGlobal, + global: &DmabufGlobal, dmabuf: Dmabuf, ) -> Result { - let device_node = dmabuf - .node() - .unwrap_or_else(|| self.primary_node.read().unwrap().unwrap()); let mut device = self .drm_devices .values_mut() - .find(|dev| dev.inner.render_node == device_node) - .ok_or(anyhow::anyhow!( - "Unable to find device for node: {}", - device_node - ))?; + .find(|device| { + device + .socket + .as_ref() + .map(|s| &s.dmabuf_global == global) + .unwrap_or(false) + }) + .context("Couldn't find gpu for dmabuf global")?; // If device advertised to client doesn't support format/modifier, select // first device that does. This is needed for image-copy from // output/toplevel on a different node. - if dmabuf.node().is_none() && !device.texture_formats.contains(&dmabuf.format()) { + // + // TODO: After + // https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/268, + // only try the device specified explicitly by the client, if set. + if !device.texture_formats.contains(&dmabuf.format()) { device = self .drm_devices .values_mut() diff --git a/src/backend/kms/surface/mod.rs b/src/backend/kms/surface/mod.rs index cbc89381..bb28bc3c 100644 --- a/src/backend/kms/surface/mod.rs +++ b/src/backend/kms/surface/mod.rs @@ -1006,16 +1006,12 @@ impl SurfaceThreadState { &self.shell.read(), ); - // Acquiring a renderer can fail transiently when the underlying DRM - // device is lost (e.g. after a GPU reset). let mut renderer = if render_node != self.target_node { self.api .renderer(&render_node, &self.target_node, compositor.format()) - .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))? + .unwrap() } else { - self.api - .single_renderer(&self.target_node) - .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))? + self.api.single_renderer(&self.target_node).unwrap() }; self.timings.start_render(&self.clock); @@ -1271,10 +1267,7 @@ impl SurfaceThreadState { }) .context("Failed to draw to offscreen render target")?; - renderer = self - .api - .single_renderer(&self.target_node) - .map_err(|err| anyhow::format_err!("Failed to create renderer: {:?}", err))?; + renderer = self.api.single_renderer(&self.target_node).unwrap(); elements = postprocess_elements( &mut renderer, @@ -1529,7 +1522,7 @@ fn get_surface_dmabuf_feedback( render_node: DrmNode, target_node: DrmNode, render_formats: FormatSet, - target_formats: FormatSet, + _target_formats: FormatSet, primary_plane_formats: FormatSet, overlay_plane_formats: Option, ) -> SurfaceDmabufFeedback { @@ -1547,40 +1540,60 @@ fn get_surface_dmabuf_feedback( .cloned() .collect::() }); + let builder = DmabufFeedbackBuilder::new(render_node.dev_id(), render_formats); - let mut builder = DmabufFeedbackBuilder::new(render_node.dev_id(), render_formats.clone()); + /* + // Sadly no implementation would pick this up as a preferred render tranche, + // where the combined formats would increase our chances of doing a dmabuf copy. + // .. So we should probably not advertise this on the off-chance it actually triggers bugs. + // - if target_node != render_node { + let combined_formats = render_formats.intersection(&target_formats).cloned().collect::(); + if target_node != render_node.dev_id() && !combined_formats.is_empty() { builder = builder.add_preference_tranche( - target_node.dev_id(), - zwp_linux_dmabuf_feedback_v1::TrancheFlags::Sampling, - target_formats, - 6..=6, + render_node.dev_id(), + None, + combined_formats, ); }; - let render_feedback = builder.clone().build().unwrap(); - let primary_scanout_feedback = builder - .clone() - .add_preference_tranche( + // We also can't advertise scan out tranches for the actual display device, + // as e.g. the nvidia driver might then send us dmabufs, that makes e.g. the iris hangs on import... + if target_node != render_node.dev_id() && !combined_formats.is_empty() { + builder = builder.add_preference_tranche( target_node.dev_id(), - zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout, - primary_plane_formats, - 4..=6, - ) - .build() - .unwrap(); - let overlay_scanout_feedback = overlay_plane_formats.map(|formats| { + Some(zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout), + combined_formats, + ); + }; + + // So no fun combinations, we gotta wait for dmabuf-v6 + */ + + let render_feedback = builder.clone().build().unwrap(); + let primary_scanout_feedback = (target_node == render_node).then(|| { builder + .clone() .add_preference_tranche( - target_node.dev_id(), - zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout, - formats, - 4..=6, + render_node.dev_id(), + Some(zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout), + primary_plane_formats, ) .build() .unwrap() }); + let overlay_scanout_feedback = overlay_plane_formats + .filter(|_| target_node == render_node) + .map(|formats| { + builder + .add_preference_tranche( + render_node.dev_id(), + Some(zwp_linux_dmabuf_feedback_v1::TrancheFlags::Scanout), + formats, + ) + .build() + .unwrap() + }); SurfaceDmabufFeedback { render_feedback, diff --git a/src/backend/render/cursor.rs b/src/backend/render/cursor.rs index 8e14d1be..da01b270 100644 --- a/src/backend/render/cursor.rs +++ b/src/backend/render/cursor.rs @@ -8,9 +8,6 @@ use crate::{ utils::prelude::*, wayland::handlers::compositor::FRAME_TIME_FILTER, }; -use keyframe::{ease, functions::EaseInOutCubic}; -use resvg::{tiny_skia, usvg}; -use serde::Deserialize; use smithay::{ backend::{ allocator::Fourcc, @@ -41,7 +38,7 @@ use smithay::{ wayland::compositor::{get_role, with_states}, }; use std::{ - collections::{HashMap, VecDeque}, + collections::HashMap, io::Read, sync::Mutex, time::{Duration, Instant}, @@ -54,43 +51,14 @@ use xcursor::{ static FALLBACK_CURSOR_DATA: &[u8] = include_bytes!("../../../resources/cursor.rgba"); -/// A single frame of a scalable SVG cursor: the parsed SVG plus its metadata. -#[derive(Debug, Clone)] -struct SvgFrame { - tree: usvg::Tree, - /// The nominal (logical) size the SVG is authored for. - nominal_size: f32, - /// Hotspot coordinates, in the SVG's own (nominal) coordinate space. - hotspot_x: f32, - hotspot_y: f32, - /// Delay to the next frame in milliseconds (0 for static cursors). - delay: u32, -} - -#[derive(Debug, Clone)] -enum CursorKind { - /// Legacy raster XCursor frames. - Xcursor(Vec), - /// Scalable SVG frames, rasterized on demand. - Svg(Vec), -} - #[derive(Debug, Clone)] pub struct Cursor { - kind: CursorKind, + icons: Vec, size: u32, } impl Cursor { pub fn load(theme: &CursorTheme, shape: CursorIcon, size: u32) -> Cursor { - // Prefer a scalable SVG cursor when the theme provides one. - if let Some(frames) = load_svg_icon(theme, shape) { - return Cursor { - kind: CursorKind::Svg(frames), - size, - }; - } - let icons = load_icon(theme, shape) .map_err(|err| warn!(?err, "Unable to load xcursor, using fallback cursor")) .or_else(|_| load_icon(theme, CursorIcon::Default)) @@ -107,134 +75,44 @@ impl Cursor { }] }); - Cursor { - kind: CursorKind::Xcursor(icons), - size, - } + Cursor { icons, size } } pub fn get_image(&self, scale: u32, millis: u32) -> Image { let size = self.size * scale; - let idx = self.frame_index(size, millis); - self.render_frame(size, idx) - } - - /// Selects the index of the frame to display at nominal size `size` (in px) - /// and elapsed `millis`. - fn frame_index(&self, size: u32, millis: u32) -> usize { - match &self.kind { - CursorKind::Xcursor(images) => xcursor_frame_index(millis, size, images), - CursorKind::Svg(frames) => svg_frame_index(millis, frames), - } - } - - /// Produces the RGBA image for frame `idx`, rasterizing SVG cursors at the - /// requested nominal size `size` (in px). - fn render_frame(&self, size: u32, idx: usize) -> Image { - match &self.kind { - CursorKind::Xcursor(images) => images[idx].clone(), - CursorKind::Svg(frames) => rasterize_svg_frame(&frames[idx], size), - } + frame(millis, size, &self.icons) } } -/// Rasterize a scalable cursor frame at nominal pixel size `size`. Per the KDE -/// SVG cursor format, the SVG canvas and hotspot are scaled by -/// `size / nominal_size`. The returned [`Image`] uses the same premultiplied -/// byte order (BGRA / little-endian ARGB) as xcursor images. -fn rasterize_svg_frame(frame: &SvgFrame, size: u32) -> Image { - let factor = size as f32 / frame.nominal_size; - let svg_size = frame.tree.size(); - let width = ((svg_size.width() * factor).floor() as u32).max(1); - let height = ((svg_size.height() * factor).floor() as u32).max(1); - - let mut image = Image { - size, - width, - height, - xhot: (frame.hotspot_x * factor).floor() as u32, - yhot: (frame.hotspot_y * factor).floor() as u32, - delay: frame.delay, - pixels_rgba: Vec::new(), - pixels_argb: Vec::new(), // unused - }; - - match tiny_skia::Pixmap::new(width, height) { - Some(mut pixmap) => { - resvg::render( - &frame.tree, - tiny_skia::Transform::from_scale(factor, factor), - &mut pixmap.as_mut(), - ); - // tiny-skia produces premultiplied RGBA; xcursor images consume the - // raw little-endian ARGB byte order (premultiplied BGRA). Swap R<->B. - let mut pixels = pixmap.take(); - for px in pixels.as_chunks_mut::<4>().0 { - px.swap(0, 2); - } - image.pixels_rgba = pixels; - } - None => { - warn!(width, height, "Failed to allocate cursor pixmap"); - image.pixels_rgba = vec![0; (width as usize) * (height as usize) * 4]; - } - } - - image -} - -/// Indices (into `images`) of all frames sharing the resolution nearest to `size`. -fn nearest_image_indices(size: u32, images: &[Image]) -> Vec { - // Follow the nominal size of the cursor to choose the nearest. +fn nearest_images(size: u32, images: &[Image]) -> impl Iterator { + // Follow the nominal size of the cursor to choose the nearest let nearest_image = images .iter() .min_by_key(|image| u32::abs_diff(size, image.size)) .unwrap(); - let (width, height) = (nearest_image.width, nearest_image.height); - images - .iter() - .enumerate() - .filter(|(_, image)| image.width == width && image.height == height) - .map(|(i, _)| i) - .collect() + images.iter().filter(move |image| { + image.width == nearest_image.width && image.height == nearest_image.height + }) } -fn xcursor_frame_index(mut millis: u32, size: u32, images: &[Image]) -> usize { - let indices = nearest_image_indices(size, images); - let total: u32 = indices.iter().map(|&i| images[i].delay).sum(); +fn frame(mut millis: u32, size: u32, images: &[Image]) -> Image { + let total = nearest_images(size, images).fold(0, |acc, image| acc + image.delay); if total == 0 { - return indices[0]; + millis = 0; + } else { + millis %= total; } - millis %= total; - for &i in &indices { - if millis <= images[i].delay { - return i; + for img in nearest_images(size, images) { + if millis <= img.delay { + return img.clone(); } - millis -= images[i].delay; + millis -= img.delay; } - *indices.last().unwrap() -} - -fn svg_frame_index(mut millis: u32, frames: &[SvgFrame]) -> usize { - let total: u32 = frames.iter().map(|frame| frame.delay).sum(); - - if total == 0 { - return 0; - } - millis %= total; - - for (i, frame) in frames.iter().enumerate() { - if millis <= frame.delay { - return i; - } - millis -= frame.delay; - } - - frames.len() - 1 + unreachable!() } #[derive(thiserror::Error, Debug)] @@ -296,79 +174,6 @@ fn load_icon(theme: &CursorTheme, shape: CursorIcon) -> Result, Error Err(Error::NoDefaultCursor) } -/// A frame entry in a `cursors_scalable//metadata.json` file, per the -/// KDE SVG cursor format specification. -#[derive(Debug, Clone, Deserialize)] -struct SvgCursorMeta { - filename: String, - nominal_size: f32, - hotspot_x: f32, - hotspot_y: f32, - /// Only present for animated cursors; defaults to 0 for static ones. - #[serde(default)] - delay: u32, -} - -/// Resolves a scalable (SVG) cursor for `shape` -fn load_svg_icon(theme: &CursorTheme, shape: CursorIcon) -> Option> { - let shape_name = shape.to_string(); - let options = usvg::Options::default(); - for name in cursor_aliases(&shape_name) - .iter() - .copied() - .chain(std::iter::once(shape_name.as_str())) - { - if let Some(dir) = theme.load_scalable(name) - && let Some(frames) = parse_svg_dir(&dir, &options) - { - return Some(frames); - } - } - - None -} - -/// Reads a `cursors_scalable/` directory (its `metadata.json` and the -/// referenced SVG files) into a list of parsed frames. -fn parse_svg_dir(dir: &std::path::Path, options: &usvg::Options) -> Option> { - let metadata = std::fs::read(dir.join("metadata.json")).ok()?; - let metas: Vec = match serde_json::from_slice(&metadata) { - Ok(metas) => metas, - Err(err) => { - warn!(?dir, ?err, "Malformed SVG cursor metadata"); - return None; - } - }; - - let mut frames = Vec::with_capacity(metas.len()); - for meta in metas { - let svg_path = dir.join(&meta.filename); - let svg_data = match std::fs::read(&svg_path) { - Ok(data) => data, - Err(err) => { - warn!(?svg_path, ?err, "Unable to read SVG cursor"); - break; - } - }; - let tree = match usvg::Tree::from_data(&svg_data, options) { - Ok(tree) => tree, - Err(err) => { - warn!(?svg_path, ?err, "Unable to parse SVG cursor"); - break; - } - }; - frames.push(SvgFrame { - tree, - nominal_size: meta.nominal_size, - hotspot_x: meta.hotspot_x, - hotspot_y: meta.hotspot_y, - delay: meta.delay, - }); - } - - (!frames.is_empty()).then_some(frames) -} - render_elements! { pub CursorRenderElement where R: ImportAll + ImportMem + AsGlowRenderer, R::TextureId: Send; Static=MemoryRenderBufferRenderElement, @@ -460,62 +265,11 @@ pub struct CursorStateInner { cursors: HashMap, current_image: Option, - image_cache: Vec, + image_cache: Vec<(Image, MemoryRenderBuffer)>, hidden: bool, idle_timer: Option, last_armed: Option, - - // shake-to-find - shake_path: VecDeque, - shake_path_position: Point, - magnify_until: Option, - magnify_target: f32, - magnification: f32, - anim_from: f32, - anim_start: Option, - rest_started: Option, -} - -/// A rasterized cursor frame, keyed by `(shape, pixel size, frame index)`. -struct CachedFrame { - key: (CursorIcon, u32, usize), - image: Image, - buffer: MemoryRenderBuffer, - unmagnified: bool, -} - -/// One sampled pointer position on the recent motion path. -#[derive(Clone, Copy)] -struct PathSample { - position: Point, - time: Instant, -} - -/// How long everything must stay unmagnified before the enlarged frames go. -const MAGNIFIED_FRAME_GRACE: Duration = Duration::from_secs(10); - -/// How far back the motion path is considered when looking for a shake. -const SHAKE_INTERVAL: Duration = Duration::from_millis(1000); -/// Path-length / bounding-box-diagonal ratio required to count as a shake. -const SHAKE_SENSITIVITY: f64 = 4.0; -/// Minimum bounding-box diagonal (logical px) before a shake is considered. -const SHAKE_DIAGONAL_MIN: f64 = 100.0; -/// Two deltas count as "the same direction" if both lie within this tolerance. -const SHAKE_SAME_SIGN_TOLERANCE: f64 = 1.0; -/// Keep the cursor enlarged for this long after the last detected shake. -const SHAKE_HOLD: Duration = Duration::from_millis(2000); -/// Extra magnification added by each shake, growing from the normal cursor size. -const OVER_MAGNIFICATION: f32 = 1.0; -/// Upper bound on the nominal size (in px) a cursor frame is rasterized at. -const MAX_RASTER_SIZE: u32 = 512; -/// Duration of the grow/shrink animation. -const MAGNIFICATION_ANIM: Duration = Duration::from_millis(200); - -/// small movement is ignored and direction stays the same -fn same_direction(a: f64, b: f64) -> bool { - (a >= -SHAKE_SAME_SIGN_TOLERANCE && b >= -SHAKE_SAME_SIGN_TOLERANCE) - || (a <= SHAKE_SAME_SIGN_TOLERANCE && b <= SHAKE_SAME_SIGN_TOLERANCE) } impl CursorStateInner { @@ -528,141 +282,14 @@ impl CursorStateInner { } pub fn get_named_cursor(&mut self, shape: CursorIcon) -> &Cursor { - let cursor_theme = &self.cursor_theme; - let cursor_size = self.cursor_size; self.cursors .entry(shape) - .or_insert_with(|| Cursor::load(cursor_theme, shape, cursor_size)) + .or_insert_with(|| Cursor::load(&self.cursor_theme, shape, self.cursor_size)) } pub fn size(&self) -> u32 { self.cursor_size } - - /// Drop the rasterizations only a magnified cursor needed, once nothing has - /// magnified it for [`MAGNIFIED_FRAME_GRACE`]. - pub fn drop_magnified_frames(&mut self, now: Instant, zoomed: bool) { - if zoomed || self.is_magnifying() { - self.rest_started = None; - return; - } - let rest_started = *self.rest_started.get_or_insert(now); - if now.duration_since(rest_started) < MAGNIFIED_FRAME_GRACE { - return; - } - - self.image_cache.retain(|frame| frame.unmagnified); - } - - /// Feed one relative-motion event into the shake detector. - pub fn detect_shake(&mut self, delta: Point, now: Instant) { - // Drop samples that have aged out of the time window. - while let Some(oldest) = self.shake_path.front() { - if now.duration_since(oldest.time) >= SHAKE_INTERVAL { - self.shake_path.pop_front(); - } else { - break; - } - } - - if delta.x != 0.0 || delta.y != 0.0 { - self.shake_path_position += delta; - let sample = PathSample { - position: self.shake_path_position, - time: now, - }; - - if self.shake_path.len() >= 2 { - let last = self.shake_path[self.shake_path.len() - 1].position; - let prev = self.shake_path[self.shake_path.len() - 2].position; - let last_delta = last - prev; - if same_direction(last_delta.x, delta.x) && same_direction(last_delta.y, delta.y) { - *self.shake_path.back_mut().unwrap() = sample; - } else { - self.shake_path.push_back(sample); - } - } else { - self.shake_path.push_back(sample); - } - } - - if self.shake_path.len() < 2 { - return; - } - - let first = self.shake_path[0].position; - let (mut left, mut top, mut right, mut bottom) = (first.x, first.y, first.x, first.y); - let mut path_length = 0.0; - for i in 1..self.shake_path.len() { - let p = self.shake_path[i].position; - left = left.min(p.x); - top = top.min(p.y); - right = right.max(p.x); - bottom = bottom.max(p.y); - - let step = p - self.shake_path[i - 1].position; - path_length += step.x.hypot(step.y); - } - - let diagonal = (right - left).hypot(bottom - top); - if diagonal < SHAKE_DIAGONAL_MIN { - return; - } - - // Path noticeably longer than the diagonal => a shake gesture. - if path_length / diagonal > SHAKE_SENSITIVITY { - self.grow(now); - self.shake_path.clear(); - } - } - - /// grow the cursor by one more increment (unbounded) - fn grow(&mut self, now: Instant) { - self.animate_to(self.magnify_target + OVER_MAGNIFICATION, now); - self.magnify_until = Some(now + SHAKE_HOLD); - } - - /// Start a 200ms `InOutCubic` tween from the current size to `target`. - fn animate_to(&mut self, target: f32, now: Instant) { - if (target - self.magnify_target).abs() < f32::EPSILON { - return; - } - self.anim_from = self.magnification; - self.anim_start = Some(now); - self.magnify_target = target; - } - - /// Advance the magnification animation and return the current factor. - pub fn animated_magnification(&mut self, now: Instant) -> f32 { - // Begin shrinking back once the hold window elapses. - if let Some(until) = self.magnify_until - && now >= until - { - self.magnify_until = None; - self.animate_to(1.0, now); - } - - self.magnification = match self.anim_start { - Some(start) => { - // `ease` clamps the time to `0.0..=1.0` for us. - let t = now.duration_since(start).as_secs_f32() / MAGNIFICATION_ANIM.as_secs_f32(); - if t >= 1.0 { - self.anim_start = None; - } - ease(EaseInOutCubic, self.anim_from, self.magnify_target, t) - } - None => self.magnify_target, - }; - self.magnification - } - - /// Whether the cursor is currently magnified or pending; drives continued redraws. - pub fn is_magnifying(&self) -> bool { - self.magnify_until.is_some() - || self.anim_start.is_some() - || self.magnification > 1.001 - || self.magnify_target > 1.001 - } } pub fn load_cursor_env() -> (String, u32) { @@ -697,34 +324,10 @@ impl Default for CursorStateInner { hidden: false, idle_timer: None, last_armed: None, - - shake_path: VecDeque::new(), - shake_path_position: Point::from((0.0, 0.0)), - magnify_until: None, - magnify_target: 1.0, - magnification: 1.0, - anim_from: 1.0, - anim_start: None, - rest_started: None, } } } -/// Pick the size a cursor frame is rasterized at, given the size the output wants -/// (`needed`) and the size it would want unmagnified (`base`). -/// -/// Rasterizations are restricted to `base * 2^n`, rounded up, and clamped to -/// [`MAX_RASTER_SIZE`]. -fn raster_size(needed: u32, base: u32) -> u32 { - let base = base.max(1); - let cap = MAX_RASTER_SIZE.max(base); - let mut rung = base; - while rung < needed && rung.saturating_mul(2) <= cap { - rung *= 2; - } - rung -} - #[profiling::function] pub fn draw_cursor( renderer: &mut R, @@ -760,53 +363,32 @@ pub fn draw_cursor( return; } - let output_scale = scale.x.max(scale.y); - let integer_scale = (output_scale * buffer_scale).ceil() as u32; - let unmagnified_px = state.size() * (output_scale.ceil() as u32); - let size_px = raster_size(state.size() * integer_scale, unmagnified_px); + let integer_scale = (scale.x.max(scale.y) * buffer_scale).ceil() as u32; + let frame = state + .get_named_cursor(current_cursor) + .get_image(integer_scale, time.as_millis()); + let actual_scale = (frame.size / state.size()).max(1); - // Pick the frame to display without rasterizing, so a cache hit avoids - // any SVG rendering. The `&Cursor` borrow is scoped to this block. - let frame_idx = { - let cursor = state.get_named_cursor(current_cursor); - cursor.frame_index(size_px, time.as_millis()) - }; - let key = (current_cursor, size_px, frame_idx); - - // Rasterize and upload this (shape, size, frame) only if not cached. - let index = match state.image_cache.iter().position(|frame| frame.key == key) { - Some(index) => index, + let pointer_images = &mut state.image_cache; + let maybe_image = pointer_images + .iter() + .find_map(|(image, texture)| if image == &frame { Some(texture) } else { None }); + let pointer_image = match maybe_image { + Some(image) => image, None => { - let image = { - let cursor = state.get_named_cursor(current_cursor); - cursor.render_frame(size_px, frame_idx) - }; - let actual_scale = (image.size / state.size()).max(1); let buffer = MemoryRenderBuffer::from_slice( - &image.pixels_rgba, + &frame.pixels_rgba, Fourcc::Argb8888, - (image.width as i32, image.height as i32), + (frame.width as i32, frame.height as i32), actual_scale as i32, Transform::Normal, None, ); - state.image_cache.push(CachedFrame { - key, - image, - buffer, - unmagnified: size_px == unmagnified_px, - }); - state.image_cache.len() - 1 + pointer_images.push((frame.clone(), buffer)); + pointer_images.last().map(|(_, i)| i).unwrap() } }; - let (frame, pointer_image) = { - let entry = &mut state.image_cache[index]; - entry.unmagnified |= size_px == unmagnified_px; - (entry.image.clone(), entry.buffer.clone()) - }; - let actual_scale = (frame.size / state.size()).max(1); - let hotspot = Point::::from((frame.xhot as i32, frame.yhot as i32)) .to_logical( actual_scale as i32, @@ -820,7 +402,7 @@ pub fn draw_cursor( MemoryRenderBufferRenderElement::from_buffer( renderer, location.to_physical(scale), - &pointer_image, + pointer_image, None, None, None, diff --git a/src/backend/render/element.rs b/src/backend/render/element.rs index cd2fb5c2..e1259dc1 100644 --- a/src/backend/render/element.rs +++ b/src/backend/render/element.rs @@ -41,9 +41,7 @@ where Workspace( RelocateRenderElement>>>, ), - Cursor( - RescaleRenderElement>>>, - ), + Cursor(RescaleRenderElement>>), Dnd(SurfaceRenderElement), MoveGrab(RescaleRenderElement>), Postprocess( diff --git a/src/backend/render/mod.rs b/src/backend/render/mod.rs index 9ad61588..e9cf651f 100644 --- a/src/backend/render/mod.rs +++ b/src/backend/render/mod.rs @@ -286,10 +286,10 @@ impl IndicatorShader { Uniform::new( "radius", [ - outer_radius[0] as f32, - outer_radius[1] as f32, - outer_radius[2] as f32, outer_radius[3] as f32, + outer_radius[1] as f32, + outer_radius[0] as f32, + outer_radius[2] as f32, ], ), Uniform::new("scale", scale as f32), @@ -510,35 +510,22 @@ pub fn cursor_elements<'a, 'frame, R>( }; let location = pointer.current_location() - output.current_location().to_f64(); - // Shake-to-find magnification, applied around the pointer tip. - let cursor_magnification = seat - .user_data() - .get::() - .map_or(1.0, |s| { - s.lock().unwrap().animated_magnification(Instant::now()) - }); - let cursor_center = location.to_physical(scale).to_i32_round(); - if mode != CursorMode::None { cursor::draw_cursor( renderer, seat, location, scale.into(), - zoom_scale * cursor_magnification as f64, + zoom_scale, now, blur_strength, mode != CursorMode::NotDefault, &mut |elem, hotspot| { push(CosmicElement::Cursor(RescaleRenderElement::from_element( - RescaleRenderElement::from_element( - RelocateRenderElement::from_element( - elem, - Point::from((-hotspot.x, -hotspot.y)), - Relocate::Relative, - ), - cursor_center, - cursor_magnification as f64, + RelocateRenderElement::from_element( + elem, + Point::from((-hotspot.x, -hotspot.y)), + Relocate::Relative, ), focal_point .as_logical() @@ -899,7 +886,8 @@ where let geometry = geometry.to_local(output).as_logical(); let padded = with_states(layer.wl_surface(), |states| { - surface_padding(states).and_then(|padding| pad_rect(geometry, &padding)) + surface_padding(states, geometry.size) + .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 87fdd2e3..37b1fdec 100644 --- a/src/backend/render/shadow.rs +++ b/src/backend/render/shadow.rs @@ -86,6 +86,12 @@ 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 b8a7935a..c4d27fac 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[0] as f32, - radii[1] as f32, - radii[2] as f32, radii[3] as f32, + radii[1] as f32, + radii[0] as f32, + radii[2] as f32, ], ), Uniform::new( diff --git a/src/backend/render/wayland/clipped_surface.rs b/src/backend/render/wayland/clipped_surface.rs index 52535269..8322079e 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[0] as f32, - radius[1] as f32, - radius[2] as f32, radius[3] as f32, + radius[1] as f32, + radius[0] as f32, + radius[2] as f32, ], ), Uniform::new( @@ -145,10 +145,10 @@ where geo: Rectangle, radius: [u8; 4], ) -> [Rectangle; 4] { - let top_left = radius[0] as f64; + let top_left = radius[3] as f64; let top_right = radius[1] as f64; - let bottom_right = radius[2] as f64; - let bottom_left = radius[3] as f64; + let bottom_right = radius[0] as f64; + let bottom_left = radius[2] as f64; [ Rectangle::new(geo.loc, Size::from((top_left, top_left))), diff --git a/src/backend/winit.rs b/src/backend/winit.rs index 8f3d14c5..0ff249a7 100644 --- a/src/backend/winit.rs +++ b/src/backend/winit.rs @@ -6,7 +6,6 @@ use crate::{ shell::{Devices, SeatExt}, state::{BackendData, Common}, utils::prelude::*, - wayland::protocols::drm::WlDrmState, }; use anyhow::{Context, Result, anyhow}; use cosmic_comp_config::output::comp::{OutputConfig, TransformDef}; @@ -274,7 +273,7 @@ fn init_egl_client_side( .create_global_with_default_feedback::(dh, &feedback); let render_node = render_node.unwrap().unwrap(); - state.common.wl_drm_state = Some(WlDrmState::new::( + let _drm_global_id = state.common.wl_drm_state.create_global::( dh, render_node .dev_path_with_type(NodeType::Render) @@ -285,7 +284,7 @@ fn init_egl_client_side( ))?, dmabuf_formats, &dmabuf_global, - )); + ); info!("EGL hardware-acceleration enabled."); } @@ -310,9 +309,7 @@ impl State { WinitEvent::Focus(true) => { for seat in self.common.shell.read().seats.iter() { let devices = seat.user_data().get::().unwrap(); - if devices - .has_device(&WinitVirtualDevice, &crate::input::InputBackendId::Normal) - { + if devices.has_device(&WinitVirtualDevice) { seat.set_active_output(&self.backend.winit().output); break; } @@ -342,9 +339,7 @@ impl State { render_ping.ping(); } WinitEvent::Redraw => render_ping.ping(), - WinitEvent::Input(event) => { - self.process_input_event(event, crate::input::InputBackendId::Normal) - } + WinitEvent::Input(event) => self.process_input_event(event), WinitEvent::CloseRequested => { self.common.should_stop = true; } diff --git a/src/backend/x11.rs b/src/backend/x11.rs index ed92e844..bd0e1b34 100644 --- a/src/backend/x11.rs +++ b/src/backend/x11.rs @@ -6,7 +6,6 @@ use crate::{ shell::{Devices, SeatExt}, state::{BackendData, Common}, utils::prelude::*, - wayland::protocols::drm::WlDrmState, }; use anyhow::{Context, Result, anyhow}; use cosmic_comp_config::output::comp::OutputConfig; @@ -498,7 +497,7 @@ where .common .dmabuf_state .create_global_with_default_feedback::(dh, &default_feedback); - state.common.wl_drm_state = Some(WlDrmState::new::( + let _drm_global_id = state.common.wl_drm_state.create_global::( dh, render_node .dev_path_with_type(NodeType::Render) @@ -509,7 +508,7 @@ where ))?, renderer.dmabuf_formats(), &dmabuf_global, - )); + ); info!("EGL hardware-acceleration enabled."); @@ -534,14 +533,14 @@ impl State { let device = event.device(); for seat in self.common.shell.read().seats.iter() { let devices = seat.user_data().get::().unwrap(); - if devices.has_device(&device, &crate::input::InputBackendId::Normal) { + if devices.has_device(&device) { seat.set_active_output(&output); break; } } }; - self.process_input_event(event, crate::input::InputBackendId::Normal); + self.process_input_event(event); // TODO actually figure out the output for output in self.common.shell.read().outputs() { self.backend.x11().schedule_render(output); diff --git a/src/config/mod.rs b/src/config/mod.rs index f8a51585..1d9b9c92 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::{ - input::InputBackendId, shell::Shell, state::{BackendData, State}, utils::prelude::OutputExt, @@ -14,11 +13,8 @@ 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}, @@ -49,8 +45,8 @@ mod types; use cosmic::config::CosmicTk; pub use cosmic_comp_config::EdidProduct; use cosmic_comp_config::{ - ActivationPolicy, AppearanceConfig, CosmicCompConfig, DecorationPreference, KeyboardConfig, - TileBehavior, XkbConfig, XwaylandDescaling, XwaylandEavesdropping, ZoomConfig, + ActivationPolicy, AppearanceConfig, CosmicCompConfig, KeyboardConfig, TileBehavior, XkbConfig, + XwaylandDescaling, XwaylandEavesdropping, ZoomConfig, input::{DeviceState as InputDeviceState, InputConfig, TouchpadOverride}, output::comp::{ OutputConfig, OutputInfo, OutputState, OutputsConfig, TransformDef, load_outputs, @@ -172,7 +168,7 @@ pub enum ColorFilter { } impl Config { - pub fn load(loop_handle: &LoopHandle<'_, State>, kiosk_mode: bool) -> Config { + pub fn load(loop_handle: &LoopHandle<'_, State>) -> Config { let config = cosmic_config::Config::new("com.system76.CosmicComp", 1).unwrap(); let source = cosmic_config::calloop::ConfigWatchSource::new(&config).unwrap(); loop_handle @@ -248,48 +244,40 @@ impl Config { // Source key bindings from com.system76.CosmicSettings.Shortcuts let settings_context = shortcuts::context().expect("Failed to load shortcuts config"); - let mut system_actions = Default::default(); - let mut shortcuts = Default::default(); - // Kiosk mode disables shortcuts - if !kiosk_mode { - system_actions = shortcuts::system_actions(&settings_context); - shortcuts = shortcuts::shortcuts(&settings_context); + let system_actions = shortcuts::system_actions(&settings_context); + let shortcuts = shortcuts::shortcuts(&settings_context); - // Listen for updates to the keybindings config. - match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) { - Ok(source) => { - if let Err(err) = - loop_handle.insert_source(source, |(config, keys), (), state| { - for key in keys { - match key.as_str() { - // Reload the keyboard shortcuts config. - "custom" | "defaults" => { - state.common.config.shortcuts = - shortcuts::shortcuts(&config); - } - - "system_actions" => { - state.common.config.system_actions = - shortcuts::system_actions(&config); - } - - _ => (), - } + // Listen for updates to the keybindings config. + match cosmic_config::calloop::ConfigWatchSource::new(&settings_context) { + Ok(source) => { + if let Err(err) = loop_handle.insert_source(source, |(config, keys), (), state| { + for key in keys { + match key.as_str() { + // Reload the keyboard shortcuts config. + "custom" | "defaults" => { + state.common.config.shortcuts = shortcuts::shortcuts(&config); } - }) - { - warn!( - ?err, - "Failed to watch com.system76.CosmicSettings.Shortcuts config" - ); + + "system_actions" => { + state.common.config.system_actions = + shortcuts::system_actions(&config); + } + + _ => (), + } } + }) { + warn!( + ?err, + "Failed to watch com.system76.CosmicSettings.Shortcuts config" + ); } - Err(err) => warn!( - ?err, - "failed to create config watch source for com.system76.CosmicSettings.Shortcuts" - ), - }; - } + } + Err(err) => warn!( + ?err, + "failed to create config watch source for com.system76.CosmicSettings.Shortcuts" + ), + }; let window_rules_context = window_rules::context().expect("Failed to load window rules config"); @@ -549,13 +537,7 @@ impl Config { primary.config_mut().xwayland_primary = true; } } - // 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 { + for output in outputs.iter().filter(|o| o.mirroring().is_none()) { { let mut config = output.config_mut(); config.position = (w, 0); @@ -787,12 +769,13 @@ 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(), - InputTime::now(), + time, |_, _, _| smithay::input::keyboard::FilterResult::<()>::Forward, ); }; @@ -837,29 +820,6 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut } } } - let ei_connections = state - .common - .ei_keyboard_source - .keys() - .cloned() - .collect::>(); - for conn in &ei_connections { - state.release_ei_keyboard(conn); - state.clear_input_source_state(&InputBackendId::Ei(conn.clone())); - } - for ei_seat in state.common.ei_seats.values() { - if let Err(err) = - ei_seat.add_keyboard("virtual keyboard", xkb_config_to_wl(&value)) - { - warn!(?err, "Failed to update libei keyboard keymap"); - } - } - if !state.common.ei_seats.is_empty() { - let seat = state.common.shell.read().seats.last_active().clone(); - if let Some(keyboard) = seat.get_keyboard() { - state.broadcast_ei_keyboard_modifiers(&keyboard); - } - } state.common.config.cosmic_conf.xkb_config = value; } "keyboard_config" => { @@ -987,10 +947,6 @@ fn config_changed(config: cosmic_config::Config, keys: Vec, state: &mut } } } - "cursor_shake_to_find" => { - let new = get_config::(&config, "cursor_shake_to_find"); - state.common.config.cosmic_conf.cursor_shake_to_find = new; - } "cursor_hide_timeout" => { let new = get_config::>(&config, "cursor_hide_timeout"); if new != state.common.config.cosmic_conf.cursor_hide_timeout { @@ -1016,13 +972,6 @@ 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/dbus/a11y_keyboard_monitor.rs b/src/dbus/a11y_keyboard_monitor.rs index c97aa590..cf66a54b 100644 --- a/src/dbus/a11y_keyboard_monitor.rs +++ b/src/dbus/a11y_keyboard_monitor.rs @@ -150,10 +150,9 @@ impl A11yKeyboardMonitorState { } pub fn key_event(&self, modifiers: &ModifiersState, keysym: &KeysymHandle, state: KeyState) { - let has_key_grab = self.has_key_grab(modifiers, keysym.modified_sym()); let clients = self.clients.lock().unwrap(); for (unique_name, client) in clients.0.iter() { - if !client.watched && !has_key_grab { + if !client.watched && !self.has_key_grab(modifiers, keysym.modified_sym()) { continue; } diff --git a/src/dbus/ei.rs b/src/dbus/ei.rs deleted file mode 100644 index 263bced4..00000000 --- a/src/dbus/ei.rs +++ /dev/null @@ -1,80 +0,0 @@ -use std::{ - os::unix::net::UnixStream, - sync::{Arc, Mutex}, -}; - -use smithay::reexports::calloop; -use zbus::names::{UniqueName, WellKnownName}; - -use super::name_owners::NameOwners; - -static ALLOWED_NAMES: &[WellKnownName] = &[ - WellKnownName::from_static_str_unchecked("org.freedesktop.impl.portal.desktop.cosmic"), - WellKnownName::from_static_str_unchecked("com.system76.CosmicOSK"), -]; - -/// Channel for handing the EI socketpair (and requested device types) -/// It's `None` until the EI sender side has been set up -type EiSender = Arc>>>; - -struct Ei { - ei_sender: EiSender, - name_owners: NameOwners, -} - -impl Ei { - async fn check_sender_allowed(&self, sender: &UniqueName<'_>) -> zbus::fdo::Result<()> { - if self.name_owners.check_owner(sender, ALLOWED_NAMES).await { - Ok(()) - } else { - Err(zbus::fdo::Error::AccessDenied("Access denied".to_string())) - } - } -} - -#[zbus::interface(name = "com.system76.CosmicComp.Ei")] -impl Ei { - /// Create a new EI sender context - async fn get_sender_socket( - &self, - device_types: u32, - #[zbus(header)] header: zbus::message::Header<'_>, - ) -> zbus::fdo::Result { - if let Some(sender) = header.sender() { - self.check_sender_allowed(sender).await?; - } - - let (comp_stream, client_stream) = UnixStream::pair().map_err(|err| { - zbus::fdo::Error::Failed(format!("Failed to create socket pair: {err}")) - })?; - - { - let guard = self.ei_sender.lock().unwrap(); - let sender = guard - .as_ref() - .ok_or_else(|| zbus::fdo::Error::Failed("EI sender not available".to_string()))?; - sender.send((comp_stream, device_types)).map_err(|err| { - zbus::fdo::Error::Failed(format!("Failed to hand off EI socket: {err}")) - })?; - } - - Ok(std::os::fd::OwnedFd::from(client_stream).into()) - } -} - -/// Register the `com.system76.CosmicComp.Ei` interface on the shared session connection. -pub async fn init( - conn: &zbus::Connection, - name_owners: &NameOwners, - ei_sender: EiSender, -) -> zbus::Result<()> { - let ei = Ei { - ei_sender, - name_owners: name_owners.clone(), - }; - conn.object_server() - .at("/com/system76/CosmicComp/Ei", ei) - .await?; - conn.request_name("com.system76.CosmicComp").await?; - Ok(()) -} diff --git a/src/dbus/mod.rs b/src/dbus/mod.rs index 9138caee..5b9754c3 100644 --- a/src/dbus/mod.rs +++ b/src/dbus/mod.rs @@ -9,13 +9,11 @@ use std::{ cell::{RefCell, RefMut}, collections::HashMap, rc::Rc, - sync::{Arc, Mutex}, }; use tracing::{error, warn}; pub mod a11y_keyboard_monitor; use a11y_keyboard_monitor::A11yKeyboardMonitorState; -pub mod ei; #[cfg(feature = "logind")] pub mod logind; mod name_owners; @@ -31,7 +29,6 @@ struct DBusStateInner { session_conn: zbus::Result, system_conn: zbus::Result, a11y_keyboard_monitor: RefCell>, - ei_sender: Arc>>>, } impl DBusState { @@ -45,7 +42,6 @@ impl DBusState { session_conn, system_conn, a11y_keyboard_monitor: RefCell::new(None), - ei_sender: Arc::new(Mutex::new(None)), })); evlh.insert_source(source, |_, _, _| {}).unwrap(); let state_clone = state.clone(); @@ -69,10 +65,6 @@ impl DBusState { RefMut::filter_map(self.0.a11y_keyboard_monitor.borrow_mut(), |x| x.as_mut()).ok() } - pub fn set_ei_sender(&self, sender: calloop::channel::Sender) { - *self.0.ei_sender.lock().unwrap() = Some(sender); - } - // TODO Lazy async init when we don't have anything blocking main thread async fn session_conn(&self) -> zbus::Result<&zbus::Connection> { self.0.session_conn.as_ref().map_err(|err| err.clone()) @@ -93,7 +85,6 @@ async fn init_session(state: &DBusState) -> zbus::Result<()> { let a11y_keyboard_monitor_state = A11yKeyboardMonitorState::new(conn, &name_owners, &state.0.executor).await?; *state.0.a11y_keyboard_monitor.borrow_mut() = Some(a11y_keyboard_monitor_state); - ei::init(conn, &name_owners, state.0.ei_sender.clone()).await?; Ok(()) } diff --git a/src/input/actions.rs b/src/input/actions.rs index 8639ba62..3d017697 100644 --- a/src/input/actions.rs +++ b/src/input/actions.rs @@ -2,7 +2,6 @@ use crate::{ config::{Action, PrivateAction}, - input::InputBackendId, shell::{ FocusResult, InvalidWorkspaceIndex, MoveResult, SeatExt, Trigger, WorkspaceDelta, focus::{FocusTarget, target::KeyboardFocusTarget}, @@ -18,7 +17,6 @@ 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}, }; @@ -30,8 +28,6 @@ use std::{os::unix::process::CommandExt, thread}; use super::gestures; -const MAX_ZOOM: f64 = 256.0; - fn propagate_by_default(action: &shortcuts::Action) -> bool { matches!( action, @@ -43,10 +39,9 @@ impl State { pub fn handle_action( &mut self, action: Action, - backend_id: &InputBackendId, seat: &Seat, serial: Serial, - time: InputTime, + time: u32, pattern: shortcuts::Binding, direction: Option, ) { @@ -74,7 +69,7 @@ impl State { Action::Shortcut(action) => { let propagate = propagate_by_default(&action); self.handle_shortcut_action( - action, backend_id, seat, serial, time, pattern, direction, propagate, + action, seat, serial, time, pattern, direction, propagate, ) } Action::Private(PrivateAction::Escape) => { @@ -148,10 +143,9 @@ impl State { pub fn handle_shortcut_action( &mut self, action: shortcuts::Action, - backend_id: &InputBackendId, seat: &Seat, serial: Serial, - time: InputTime, + time: u32, pattern: shortcuts::Binding, direction: Option, propagate: bool, @@ -238,7 +232,6 @@ impl State { { self.handle_shortcut_action( Action::SwitchOutput(inferred), - backend_id, seat, serial, time, @@ -278,7 +271,6 @@ impl State { { self.handle_shortcut_action( Action::SwitchOutput(inferred), - backend_id, seat, serial, time, @@ -400,7 +392,6 @@ impl State { } else { Action::SendToOutput(inferred) }, - backend_id, seat, serial, time, @@ -426,7 +417,6 @@ impl State { } else { Action::SendToWorkspace(1) }, - backend_id, seat, serial, time, @@ -493,7 +483,6 @@ impl State { } else { Action::SendToOutput(inferred) }, - backend_id, seat, serial, time, @@ -519,7 +508,6 @@ impl State { } else { Action::SendToLastWorkspace }, - backend_id, seat, serial, time, @@ -544,9 +532,7 @@ impl State { if propagate && let Some((serial, prev_output, prev_idx)) = shell.previous_workspace_idx.take() - && seat - .last_modifier_change_for(backend_id) - .is_some_and(|s| s == serial) + && seat.last_modifier_change().is_some_and(|s| s == serial) && prev_output == current_output { let _ = shell.activate( @@ -719,7 +705,6 @@ impl State { if res.is_ok() { self.handle_shortcut_action( Action::SwitchOutput(direction), - backend_id, seat, serial, time, @@ -756,8 +741,7 @@ impl State { }; if let Some(direction) = dir { - if let Some(last_mod_serial) = seat.last_modifier_change_for(backend_id) - { + if let Some(last_mod_serial) = seat.last_modifier_change() { let mut shell = self.common.shell.write(); if !shell .previous_workspace_idx @@ -792,7 +776,6 @@ impl State { self.handle_shortcut_action( action, - backend_id, seat, serial, time, @@ -817,7 +800,7 @@ impl State { .move_current_element(direction, seat); match res { MoveResult::MoveFurther(_move_further) => { - if let Some(last_mod_serial) = seat.last_modifier_change_for(backend_id) { + if let Some(last_mod_serial) = seat.last_modifier_change() { let mut shell = self.common.shell.write(); if !shell .previous_workspace_idx @@ -851,7 +834,6 @@ impl State { self.handle_shortcut_action( action, - backend_id, seat, serial, time, @@ -1119,14 +1101,7 @@ impl State { } if zoom_seat == *seat { - let factor = 1.0 + change.abs(); - let new_level = if change < 0. { - current_level / factor - } else { - current_level * factor - } - .clamp(1.0, MAX_ZOOM); - let new_level = if new_level < 1.01 { 1.0 } else { new_level }; + let new_level = (current_level + change).max(1.0); shell.trigger_zoom( seat, Some(&output), diff --git a/src/input/mod.rs b/src/input/mod.rs index af160ae2..0cb26a9d 100644 --- a/src/input/mod.rs +++ b/src/input/mod.rs @@ -9,17 +9,14 @@ use crate::{ cosmic_modifiers_from_smithay, }, }, - input::{ - gestures::{GestureState, SwipeAction}, - tablet_emu::PointerEmulationGrab, - }, + input::gestures::{GestureState, SwipeAction}, shell::{ - SeatExt, Trigger, + LastModifierChange, SeatExt, Trigger, focus::{ Stage, render_input_order, target::{KeyboardFocusTarget, PointerFocusTarget}, }, - grabs::{MenuGrab, MoveGrab, ReleaseMode, ResizeEdge, ResizeGrab}, + grabs::{ReleaseMode, ResizeEdge}, layout::{ floating::ResizeGrabMarker, tiling::{NodeDesc, SwapWindowGrab, TilingLayout}, @@ -45,23 +42,20 @@ use smithay::{ backend::input::{ AbsolutePositionEvent, Axis, AxisRelativeDirection, AxisSource, Device, DeviceCapability, GestureBeginEvent, GestureEndEvent, GesturePinchUpdateEvent as _, - GestureSwipeUpdateEvent as _, InputBackend, InputEvent, InputTime, KeyState, + GestureSwipeUpdateEvent as _, InputBackend, InputEvent, KeyState, KeyboardKeyEvent, PointerAxisEvent, ProximityState, TabletToolButtonEvent, TabletToolEvent, TabletToolProximityEvent, TabletToolTipEvent, TabletToolTipState, TouchEvent, }, - desktop::{WindowSurfaceType, utils::under_from_surface_tree}, + desktop::{PopupKeyboardGrab, WindowSurfaceType, utils::under_from_surface_tree}, input::{ Seat, - keyboard::KeyboardHandle, - keyboard::{FilterResult, KeyboardSource, KeysymHandle, ModifiersState}, + keyboard::{FilterResult, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame, ButtonEvent as PointerButtonEvent, Focus, GestureHoldBeginEvent, - GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, - GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, - GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, PointerGrab, PointerHandle, - RelativeMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, + PointerGrab, PointerHandle, RelativeMotionEvent, }, - tablet::{TabletDescriptor, TabletSeatTrait, tool}, touch::{DownEvent, MotionEvent as TouchMotionEvent, UpEvent}, }, output::Output, @@ -69,13 +63,14 @@ use smithay::{ input::Device as InputDevice, wayland_server::{Resource as _, protocol::wl_surface::WlSurface}, }, - utils::{Clock, Logical, Monotonic, Point, Rectangle, SERIAL_COUNTER, Serial, Size}, + utils::{Clock, Logical, Monotonic, Point, Rectangle, SERIAL_COUNTER, Serial}, wayland::{ compositor::CompositorHandler, image_copy_capture::CursorSessionRef, keyboard_shortcuts_inhibit::KeyboardShortcutsInhibitorSeat, pointer_constraints::{PointerConstraint, with_pointer_constraint}, seat::WaylandFocus, + tablet_manager::{TabletDescriptor, TabletSeatTrait}, }, }; use tracing::{error, trace}; @@ -85,27 +80,13 @@ use std::{ any::Any, borrow::Cow, cell::RefCell, - collections::{HashMap, HashSet}, + collections::HashSet, ops::ControlFlow, time::{Duration, Instant}, }; 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 -/// [`smithay::backend::input::Device::id`]). -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum InputBackendId { - /// The session input backend (libinput / winit / x11) these are mutually exclusive - Normal, - /// A specific Ei client connection - Ei(smithay::reexports::reis::eis::Connection), - /// The `zwp_virtual_keyboard_v1` protocol (all virtual keyboards share this source) - VirtualKeyboard, -} /// Used for debouncing focus updates due to pointer motion, if after the focus change is /// triggered the event will cancel if the pointer moves to the original target @@ -119,35 +100,19 @@ pub struct PointerFocusState { } #[derive(Default)] -pub struct SupressedKeys( - RefCell)>>>, -); +pub struct SupressedKeys(RefCell)>>); #[derive(Default)] -pub struct SupressedButtons(RefCell>>); +pub struct SupressedButtons(RefCell>); #[derive(Default, Debug)] -pub struct ModifiersShortcutQueue(RefCell>); +pub struct ModifiersShortcutQueue(RefCell>); impl SupressedKeys { - fn add( - &self, - backend_id: &InputBackendId, - keysym: &KeysymHandle, - token: impl Into>, - ) { - self.0 - .borrow_mut() - .entry(backend_id.clone()) - .or_default() - .push((keysym.raw_code(), token.into())); + fn add(&self, keysym: &KeysymHandle, token: impl Into>) { + self.0.borrow_mut().push((keysym.raw_code(), token.into())); } - fn filter( - &self, - backend_id: &InputBackendId, - keysym: &KeysymHandle, - ) -> Option> { - let mut by_source = self.0.borrow_mut(); - let keys = by_source.get_mut(backend_id)?; + fn filter(&self, keysym: &KeysymHandle) -> Option> { + let mut keys = self.0.borrow_mut(); let (removed, remaining) = keys .drain(..) .partition(|(key, _)| *key == keysym.raw_code()); @@ -164,60 +129,44 @@ impl SupressedKeys { .collect::>(), ) } - - fn clear_source(&self, backend_id: &InputBackendId) { - self.0.borrow_mut().remove(backend_id); - } } impl SupressedButtons { - fn add(&self, backend_id: &InputBackendId, button: u32) { - self.0 - .borrow_mut() - .entry(backend_id.clone()) - .or_default() - .insert(button); + fn add(&self, button: u32) { + self.0.borrow_mut().insert(button); } - fn remove(&self, backend_id: &InputBackendId, button: u32) -> bool { - self.0 - .borrow_mut() - .get_mut(backend_id) - .is_some_and(|buttons| buttons.remove(&button)) - } - - fn clear_source(&self, backend_id: &InputBackendId) { - self.0.borrow_mut().remove(backend_id); + fn remove(&self, button: u32) -> bool { + self.0.borrow_mut().remove(&button) } } impl ModifiersShortcutQueue { - pub fn set(&self, backend_id: &InputBackendId, binding: shortcuts::Binding) { - self.0.borrow_mut().insert(backend_id.clone(), binding); + pub fn set(&self, binding: shortcuts::Binding) { + let mut set = self.0.borrow_mut(); + *set = Some(binding); } - pub fn take(&self, backend_id: &InputBackendId, binding: &shortcuts::Binding) -> bool { + pub fn take(&self, binding: &shortcuts::Binding) -> bool { let mut set = self.0.borrow_mut(); - if set.get(backend_id).is_some_and(|queued| queued == binding) { - set.remove(backend_id); + if set.is_some() && set.as_ref().unwrap() == binding { + *set = None; true } else { false } } - pub fn clear(&self, backend_id: &InputBackendId) { - self.0.borrow_mut().remove(backend_id); + pub fn clear(&self) { + let mut set = self.0.borrow_mut(); + *set = None; } } impl State { #[profiling::function] - pub fn process_input_event( - &mut self, - event: InputEvent, - backend_id: InputBackendId, - ) where + pub fn process_input_event(&mut self, event: InputEvent) + where ::Device: 'static, { crate::wayland::handlers::output_power::set_all_surfaces_dpms_on(self); @@ -228,25 +177,19 @@ impl State { let shell = self.common.shell.read(); let seat = shell.seats.last_active(); let led_state = seat.get_keyboard().unwrap().led_state(); - seat.devices().add_device(&device, led_state, &backend_id); + seat.devices().add_device(&device, led_state); if device.has_capability(DeviceCapability::TabletTool) { - seat.tablet_seat().add_wp_tablet( + seat.tablet_seat().add_tablet::( &self.common.display_handle, &TabletDescriptor::from(&device), ); } - let has_keyboard = device.has_capability(DeviceCapability::Keyboard); - std::mem::drop(shell); - // send the seat's current modifier state to the new ei keyboard - if has_keyboard && let InputBackendId::Ei(conn) = &backend_id { - self.send_ei_keyboard_modifiers(conn); - } } InputEvent::DeviceRemoved { device } => { for seat in &mut self.common.shell.read().seats.iter() { let devices = seat.devices(); - if devices.has_device(&device, &backend_id) { - devices.remove_device(&device, &backend_id); + if devices.has_device(&device) { + devices.remove_device(&device); if device.has_capability(DeviceCapability::TabletTool) { seat.tablet_seat() .remove_tablet(&TabletDescriptor::from(&device)); @@ -267,7 +210,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -277,7 +220,7 @@ impl State { trace!(?keycode, ?state, "key"); let serial = SERIAL_COUNTER.next_serial(); - let time = Event::time(&event); + let time = Event::time_msec(&event); let keyboard = seat.get_keyboard().unwrap(); let previous_modifiers = keyboard.modifier_state(); if let Some((action, pattern)) = keyboard @@ -288,17 +231,51 @@ impl State { serial, time, |data, modifiers, handle| { - data.process_keyboard_filter( - &backend_id, - &seat, - modifiers, - handle, - serial, - time, - keycode, - state, - previous_modifiers, - ) + if previous_modifiers != *modifiers { + *seat + .user_data() + .get::() + .unwrap() + .0 + .lock() + .unwrap() = Some(serial); + } + + let current_focus = seat.get_keyboard().unwrap().current_focus(); + let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| { + f.wl_surface() + .map(|surface| { + seat.keyboard_shortcuts_inhibitor_for_surface(&surface) + .map(|inhibitor| inhibitor.is_active()) + .unwrap_or(false) + || seat.has_active_xwayland_grab(&surface) + }) + .unwrap_or(false) + }); + let sym = handle.modified_sym(); + + let result = Self::filter_keyboard_input( + data, &event, &seat, modifiers, handle, serial, + ); + + if (matches!(result, FilterResult::Forward) + && !seat.get_keyboard().unwrap().is_grabbed() + && !shortcuts_inhibited + && !matches!( + current_focus, + Some(KeyboardFocusTarget::LockSurface(_)) + )) + // we don't want to accidentally leave any keys pressed + // and do more filtering in `xwayland_notify_key_event` + // for released keys + || state == KeyState::Released + { + data.common.xwayland_notify_key_event( + sym, keycode, state, serial, time, + ); + } + + result }, ) .flatten() @@ -309,7 +286,7 @@ impl State { FilterResult::<()>::Forward }); } - self.handle_action(action, &backend_id, &seat, serial, time, pattern, None) + self.handle_action(action, &seat, serial, time, pattern, None) } // If we want to track numlock state so it can be reused on the next boot... @@ -331,36 +308,14 @@ impl State { } InputEvent::PointerMotion { event, .. } => { - use smithay::backend::input::PointerMotionEvent as _; + use smithay::backend::input::PointerMotionEvent; let shell = self.common.shell.write(); - if let Some(seat) = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned() - { + if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); 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::() - { - let active = { - let mut cursor = cursor_state.lock().unwrap(); - cursor.detect_shake(event.delta(), std::time::Instant::now()); - cursor.is_magnifying() - }; - if active { - self.backend.schedule_render(¤t_output); - } - } - let mut position = seat.get_pointer().unwrap().current_location().as_global(); let under = State::surface_under(position, ¤t_output, &shell) @@ -406,7 +361,7 @@ impl State { &RelativeMotionEvent { delta: event.delta(), delta_unaccel: event.delta_unaccel(), - time: event.time(), + utime: event.time(), }, ); @@ -438,12 +393,10 @@ impl State { // - output_geometry.size so that we don't send leave events to a fullscreen app // - logical size so that the position doesn't end up outside the actual size of the output // See https://github.com/pop-os/cosmic-comp/pull/2568 - let max_x = (output_geometry_loc.x - + logical.w.min(output_geometry.size.w as f64)) - .next_down(); - let max_y = (output_geometry_loc.y - + logical.h.min(output_geometry.size.h as f64)) - .next_down(); + let max_x = output_geometry_loc.x + + logical.w.min(output_geometry.size.w as f64).next_down(); + let max_y = output_geometry_loc.y + + logical.h.min(output_geometry.size.h as f64).next_down(); position.x = position.x.clamp(output_geometry_loc.x, max_x); position.y = position.y.clamp(output_geometry_loc.y, max_y); @@ -644,10 +597,10 @@ impl State { ptr.motion( self, under, - &PointerMotionEvent { + &MotionEvent { location: position.as_logical(), serial, - time: event.time(), + time: event.time_msec(), }, ); ptr.frame(self); @@ -710,47 +663,19 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); - let (output, position) = if matches!(&backend_id, InputBackendId::Ei(_)) { - // EI absolute coordinates are in the compositor's *global* - // logical space: each advertised region carries its output's - // global offset, so the client sends a global position. Use - // the coordinate directly and find the output it lands in, - // rather than mapping relative to the focused output (which - // cannot address other monitors). This is the KWin/mutter - // model. - let position = - smithay::backend::input::AbsolutePositionEvent::position_transformed( - &event, - // smithay's EI impl ignores the size and returns the - // raw coordinate. - Size::from((0, 0)), - ) - .as_global(); - let output = self - .common - .shell - .read() - .outputs() - .find(|o| o.geometry().to_f64().contains(position)) - .cloned() - .unwrap_or_else(|| seat.active_output()); - (output, position) - } else { - let output = seat.active_output(); - let output_geometry = output.geometry(); - let position = output_geometry.loc.to_f64() - + smithay::backend::input::AbsolutePositionEvent::position_transformed( - &event, - output_geometry.size.as_logical(), - ) - .as_global(); - (output, position) - }; + let output = seat.active_output(); + let output_geometry = output.geometry(); + let position = output_geometry.loc.to_f64() + + smithay::backend::input::AbsolutePositionEvent::position_transformed( + &event, + output_geometry.size.as_logical(), + ) + .as_global(); let serial = SERIAL_COUNTER.next_serial(); let under = State::surface_under(position, &output, &self.common.shell.write()) .map(|(target, pos)| (target, pos.as_logical())); @@ -759,33 +684,15 @@ impl State { ptr.motion( self, under, - &PointerMotionEvent { + &MotionEvent { location: position.as_logical(), serial, - time: event.time(), + time: event.time_msec(), }, ); 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); - } - - shell.update_pointer_position(position.to_local(&output), &output); - shell.update_focal_point( - &seat, - position, - self.common.config.cosmic_conf.accessibility_zoom.view_moves, - ); - + let shell = self.common.shell.read(); update_output_image_copy_cursor_position( &shell, &self.common.clock, @@ -796,14 +703,15 @@ impl State { } } InputEvent::PointerButton { event, .. } => { - use smithay::backend::input::{ButtonState, PointerButtonEvent as _}; + use smithay::backend::input::{ButtonState, PointerButtonEvent}; + // let Some(seat) = self .common .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned() else { return; @@ -826,26 +734,7 @@ impl State { let serial = SERIAL_COUNTER.next_serial(); let button = event.button_code(); - // Track buttons held by a libei source so they can be released if the connection - // drops mid-press - if let InputBackendId::Ei(conn) = &backend_id { - match event.state() { - ButtonState::Pressed => { - self.common - .ei_pointer_buttons - .entry(conn.clone()) - .or_default() - .insert(button); - } - ButtonState::Released => { - if let Some(held) = self.common.ei_pointer_buttons.get_mut(conn) { - held.remove(&button); - } - } - } - } - - let mut pass_event = !seat.supressed_buttons().remove(&backend_id, button); + let mut pass_event = !seat.supressed_buttons().remove(button); if event.state() == ButtonState::Pressed { // change the keyboard focus unless the pointer is grabbed // We test for any matching surface type here but always use the root @@ -867,29 +756,28 @@ impl State { ); if let Some(target) = under.filter(|_| !on_resize_fork) { if let Some(surface) = target.toplevel().map(Cow::into_owned) - && self.source_modifiers(&backend_id, &seat).logo + && seat.get_keyboard().unwrap().modifier_state().logo && !shortcuts_inhibited { let seat_clone = seat.clone(); - let mouse_button = event.button(); + let mouse_button = PointerButtonEvent::button(&event); let mut supress_button = || { // If the logo is held then the pointer event is // aimed at the compositor and shouldn't be passed // to the application. pass_event = false; - seat.supressed_buttons().add(&backend_id, button); + seat.supressed_buttons().add(button); }; fn dispatch_grab + 'static>( grab: Option<(G, smithay::input::pointer::Focus)>, seat: Seat, - backend_id: &InputBackendId, serial: Serial, state: &mut State, ) { if let Some((target, focus)) = grab { - seat.modifiers_shortcut_queue().clear(backend_id); + seat.modifiers_shortcut_queue().clear(); seat.get_pointer() .unwrap() @@ -901,7 +789,6 @@ impl State { match mouse_button { smithay::backend::input::MouseButton::Left => { supress_button(); - let backend_id = backend_id.clone(); self.common.event_loop_handle.insert_idle( move |state| { let mut shell = state.common.shell.write(); @@ -916,19 +803,12 @@ impl State { false, ); drop(shell); - dispatch_grab( - res, - seat_clone, - &backend_id, - serial, - state, - ); + dispatch_grab(res, seat_clone, serial, state); }, ); } smithay::backend::input::MouseButton::Right => { supress_button(); - let backend_id = backend_id.clone(); self.common.event_loop_handle.insert_idle( move |state| { let mut shell = state.common.shell.write(); @@ -986,13 +866,7 @@ impl State { false, ); drop(shell); - dispatch_grab( - res, - seat_clone, - &backend_id, - serial, - state, - ); + dispatch_grab(res, seat_clone, serial, state); }, ); } @@ -1023,7 +897,7 @@ impl State { button, event.state(), serial, - event.time(), + event.time_msec(), ); } @@ -1031,16 +905,16 @@ impl State { if pass_event { ptr.button( self, - &PointerButtonEvent { + &ButtonEvent { button, state: event.state(), serial, - time: event.time(), + time: event.time_msec(), }, ); ptr.frame(self); } else if event.state() == ButtonState::Released { - ptr.unset_grab(self, serial, event.time()) + ptr.unset_grab(self, serial, event.time_msec()) } } InputEvent::PointerAxis { event, .. } => { @@ -1056,13 +930,13 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); - if self.source_modifiers(&backend_id, &seat).logo + if seat.get_keyboard().unwrap().modifier_state().logo && self .common .config @@ -1070,7 +944,7 @@ impl State { .accessibility_zoom .enable_mouse_zoom_shortcuts { - seat.modifiers_shortcut_queue().clear(&backend_id); + seat.modifiers_shortcut_queue().clear(); if let Some(mut percentage) = event .amount_v120(Axis::Vertical) .map(|val| val / 120.) @@ -1091,11 +965,8 @@ impl State { self.update_zoom(&seat, change, event.source() == AxisSource::Wheel); } } else { - 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.)); - if let Some(horizontal_amount) = horizontal_amount { + let mut frame = AxisFrame::new(event.time_msec()).source(event.source()); + if let Some(horizontal_amount) = event.amount(Axis::Horizontal) { if horizontal_amount != 0.0 { frame = frame .relative_direction( @@ -1113,10 +984,7 @@ impl State { frame = frame.stop(Axis::Horizontal); } } - let vertical_amount = event - .amount(Axis::Vertical) - .or_else(|| Some(event.amount_v120(Axis::Vertical)? * 15.0 / 120.)); - if let Some(vertical_amount) = vertical_amount { + if let Some(vertical_amount) = event.amount(Axis::Vertical) { if vertical_amount != 0.0 { frame = frame .relative_direction( @@ -1147,7 +1015,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1160,7 +1028,7 @@ impl State { self, &GestureSwipeBeginEvent { serial, - time: event.time(), + time: event.time_msec(), fingers: event.fingers(), }, ); @@ -1173,7 +1041,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1181,7 +1049,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().millis() as u64), + Duration::from_millis(event.time_msec() as u64), ); // Decide on action if first update if first_update { @@ -1257,7 +1125,7 @@ impl State { pointer.gesture_swipe_update( self, &GestureSwipeUpdateEvent { - time: event.time(), + time: event.time_msec(), delta: event.delta(), }, ); @@ -1274,7 +1142,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1306,7 +1174,7 @@ impl State { self, &GestureSwipeEndEvent { serial, - time: event.time(), + time: event.time_msec(), cancelled: event.cancelled(), }, ); @@ -1319,7 +1187,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1329,7 +1197,7 @@ impl State { self, &GesturePinchBeginEvent { serial, - time: event.time(), + time: event.time_msec(), fingers: event.fingers(), }, ); @@ -1341,7 +1209,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1349,7 +1217,7 @@ impl State { pointer.gesture_pinch_update( self, &GesturePinchUpdateEvent { - time: event.time(), + time: event.time_msec(), delta: event.delta(), scale: event.scale(), rotation: event.rotation(), @@ -1363,7 +1231,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1373,7 +1241,7 @@ impl State { self, &GesturePinchEndEvent { serial, - time: event.time(), + time: event.time_msec(), cancelled: event.cancelled(), }, ); @@ -1385,7 +1253,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1395,7 +1263,7 @@ impl State { self, &GestureHoldBeginEvent { serial, - time: event.time(), + time: event.time_msec(), fingers: event.fingers(), }, ); @@ -1407,7 +1275,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1417,7 +1285,7 @@ impl State { self, &GestureHoldEndEvent { serial, - time: event.time(), + time: event.time_msec(), cancelled: event.cancelled(), }, ); @@ -1426,40 +1294,17 @@ impl State { InputEvent::TouchDown { event, .. } => { let shell = self.common.shell.write(); - if let Some(seat) = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned() - { + if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { self.common.idle_notifier_state.notify_activity(&seat); - // Check if the touch is from an ei device or a mapped device - // EI absolute coordinates are already in the compositor's global logical - // space (each advertised region carries its output's global offset), so use - // them directly and find the output they land in. - let (output, position) = if matches!(&backend_id, InputBackendId::Ei(_)) { - let position = - smithay::backend::input::AbsolutePositionEvent::position_transformed( - &event, - Size::from((0, 0)), - ) - .as_global(); - let output = shell - .outputs() - .find(|o| o.geometry().to_f64().contains(position)) + let Some(output) = + mapped_output_for_device(&self.common.config, &shell, &event.device()) .cloned() - .unwrap_or_else(|| seat.active_output()); - (output, position) - } else { - let Some(output) = - mapped_output_for_device(&self.common.config, &shell, &event.device()) - .cloned() - else { - return; - }; - let position = - transform_output_mapped_position(&output, &event, shell.zoom_state()); - (output, position) + else { + return; }; + + let position = + transform_output_mapped_position(&output, &event, shell.zoom_state()); let under = State::surface_under(position, &output, &shell) .map(|(target, pos)| (target, pos.as_logical())); @@ -1474,43 +1319,24 @@ impl State { slot: event.slot(), location: position.as_logical(), serial, - time: event.time(), + time: event.time_msec(), }, ); } } InputEvent::TouchMotion { event, .. } => { let shell = self.common.shell.write(); - if let Some(seat) = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned() - { + if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { self.common.idle_notifier_state.notify_activity(&seat); - let (output, position) = if matches!(&backend_id, InputBackendId::Ei(_)) { - let position = - smithay::backend::input::AbsolutePositionEvent::position_transformed( - &event, - Size::from((0, 0)), - ) - .as_global(); - let output = shell - .outputs() - .find(|o| o.geometry().to_f64().contains(position)) + let Some(output) = + mapped_output_for_device(&self.common.config, &shell, &event.device()) .cloned() - .unwrap_or_else(|| seat.active_output()); - (output, position) - } else { - let Some(output) = - mapped_output_for_device(&self.common.config, &shell, &event.device()) - .cloned() - else { - return; - }; - let position = - transform_output_mapped_position(&output, &event, shell.zoom_state()); - (output, position) + else { + return; }; + + let position = + transform_output_mapped_position(&output, &event, shell.zoom_state()); let under = State::surface_under(position, &output, &shell) .map(|(target, pos)| (target, pos.as_logical())); @@ -1523,7 +1349,7 @@ impl State { &TouchMotionEvent { slot: event.slot(), location: position.as_logical(), - time: event.time(), + time: event.time_msec(), }, ); } @@ -1536,10 +1362,7 @@ impl State { shell.set_overview_mode(None, self.common.event_loop_handle.clone()); } - let maybe_seat = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned(); + let maybe_seat = shell.seats.for_device(&event.device()).cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); std::mem::drop(shell); @@ -1549,7 +1372,7 @@ impl State { self, &UpEvent { slot: event.slot(), - time: event.time(), + time: event.time_msec(), serial, }, ); @@ -1561,7 +1384,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1575,7 +1398,7 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); @@ -1586,11 +1409,7 @@ impl State { InputEvent::TabletToolAxis { event, .. } => { let shell = self.common.shell.write(); - if let Some(seat) = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned() - { + if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); let Some(output) = @@ -1600,7 +1419,6 @@ 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) @@ -1609,92 +1427,55 @@ impl State { std::mem::drop(shell); let pointer = seat.get_pointer().unwrap(); - pointer.set_location(position.as_logical()); + pointer.motion( + self, + under.clone(), + &MotionEvent { + location: position.as_logical(), + serial: SERIAL_COUNTER.next_serial(), + time: self.common.clock.now().as_millis(), + }, + ); let tablet_seat = seat.tablet_seat(); + let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device())); 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, - ); + if let (Some(tablet), Some(tool)) = (tablet, tool) { + if event.pressure_has_changed() { + tool.pressure(event.pressure()); + } + if event.distance_has_changed() { + tool.distance(event.distance()); + } + if event.tilt_has_changed() { + tool.tilt(event.tilt()); + } + if event.slider_has_changed() { + tool.slider_position(event.slider_position()); + } + if event.rotation_has_changed() { + tool.rotation(event.rotation()); + } + if event.wheel_has_changed() { + tool.wheel(event.wheel_delta(), event.wheel_delta_discrete()); } - - let frame = tool::AxisFrame { - pressure: event.pressure_has_changed().then(|| event.pressure()), - distance: event.distance_has_changed().then(|| event.distance()), - - tilt: event.tilt_has_changed().then(|| event.tilt()), - rotation: event.rotation_has_changed().then(|| event.rotation()), - - slider: event.slider_has_changed().then(|| event.slider_position()), - wheel: event - .wheel_has_changed() - .then(|| (event.wheel_delta(), event.wheel_delta_discrete())), - }; - - tool.axis(self, frame); tool.motion( - self, - under, - &tool::MotionEvent { - location: position.as_logical(), - serial, - time: event.time(), - }, + position.as_logical(), + under + .and_then(|(f, loc)| f.wl_surface().map(|s| (s.into_owned(), loc))), + &tablet, + SERIAL_COUNTER.next_serial(), + 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, .. } => { let shell = self.common.shell.write(); - if let Some(seat) = shell - .seats - .for_device(&event.device(), &backend_id) - .cloned() - { + if let Some(seat) = shell.seats.for_device(&event.device()).cloned() { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); let Some(output) = @@ -1704,7 +1485,6 @@ 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) @@ -1713,178 +1493,62 @@ impl State { std::mem::drop(shell); let pointer = seat.get_pointer().unwrap(); - pointer.set_location(position.as_logical()); + pointer.motion( + self, + under.clone(), + &MotionEvent { + location: position.as_logical(), + serial: SERIAL_COUNTER.next_serial(), + time: self.common.clock.now().as_millis(), + }, + ); let tablet_seat = seat.tablet_seat(); let tablet = tablet_seat.get_tablet(&TabletDescriptor::from(&event.device())); let dh = self.common.display_handle.clone(); - let tool = tablet_seat - .get_tool(&event.tool()) - .unwrap_or_else(|| tablet_seat.add_wp_tool(self, &dh, &event.tool())); + let tool = tablet_seat.add_tool::(self, &dh, &event.tool()); 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()), - - tilt: event.tilt_has_changed().then(|| event.tilt()), - rotation: event.rotation_has_changed().then(|| event.rotation()), - - slider: event.slider_has_changed().then(|| event.slider_position()), - wheel: event - .wheel_has_changed() - .then(|| (event.wheel_delta(), event.wheel_delta_discrete())), - }; - match event.state() { ProximityState::In => { - tool.proximity_in( - self, - under, - tablet, - &tool::ProximityInEvent { - location: position.as_logical(), - axis: Some(frame), - 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(), - }, - ); + if let Some(under) = under.and_then(|(f, loc)| { + f.wl_surface().map(|s| (s.into_owned(), loc)) + }) { + tool.proximity_in( + position.as_logical(), + under, + &tablet, + SERIAL_COUNTER.next_serial(), + event.time_msec(), + ) } } + ProximityState::Out => tool.proximity_out(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 .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); 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() { TabletToolTipState::Down => { - tool.down( - self, - &tool::DownEvent { - serial, - time: event.time(), - }, - ); + tool.tip_down(SERIAL_COUNTER.next_serial(), event.time_msec()); } TabletToolTipState::Up => { - tool.up( - self, - &tool::UpEvent { - serial, - time: event.time(), - }, - ); + tool.tip_up(event.time_msec()); } } - - tool.frame(self, event.time()); } } } @@ -1894,23 +1558,18 @@ impl State { .shell .read() .seats - .for_device(&event.device(), &backend_id) + .for_device(&event.device()) .cloned(); if let Some(seat) = maybe_seat { self.common.idle_notifier_state.notify_activity(&seat); notify_cursor_activity(self, &seat); if let Some(tool) = seat.tablet_seat().get_tool(&event.tool()) { tool.button( - self, - &tool::ButtonEvent { - button: event.button(), - state: event.button_state(), - serial: SERIAL_COUNTER.next_serial(), - time: event.time(), - }, + event.button(), + event.button_state(), + SERIAL_COUNTER.next_serial(), + event.time_msec(), ); - - tool.frame(self, event.time()); } } } @@ -1956,344 +1615,15 @@ impl State { } } - /// The modifier state held by the source that produced an event. - pub(crate) fn source_modifiers( - &self, - _backend_id: &InputBackendId, - seat: &Seat, - ) -> ModifiersState { - seat.get_keyboard() - .map(|k| k.modifier_state()) - .unwrap_or_default() - } - - pub(crate) fn clear_input_source_state(&mut self, backend_id: &InputBackendId) { - let seats = self - .common - .shell - .read() - .seats - .iter() - .cloned() - .collect::>(); - for seat in seats { - seat.supressed_keys().clear_source(backend_id); - seat.supressed_buttons().clear_source(backend_id); - seat.modifiers_shortcut_queue().clear(backend_id); - seat.clear_last_modifier_change(backend_id); - } - } - - /// Release the keys this libei connection still holds on the shared seat, so they don't stay - /// stuck in the focused client. Keeps the connection's source valid (only clears held keys), - /// so it's safe to call both on disconnect and on a keymap change. Does not remove the source - /// from [`Common::ei_keyboard_source`], the disconnect path does that. - pub(crate) fn release_ei_keyboard(&mut self, conn: &smithay::reexports::reis::eis::Connection) { - let seat = self.common.shell.read().seats.last_active().clone(); - let Some(keyboard) = seat.get_keyboard() else { - return; - }; - if let Some(source) = self.common.ei_keyboard_source.get(conn).copied() { - keyboard.release_source(self, source); - } - } - - /// Release any pointer buttons this libei connection still holds - pub(crate) fn release_ei_pointer(&mut self, conn: &smithay::reexports::reis::eis::Connection) { - let buttons: Vec = self - .common - .ei_pointer_buttons - .get(conn) - .map(|held| held.iter().copied().collect()) - .unwrap_or_default(); - if buttons.is_empty() { - return; - } - let seat = self.common.shell.read().seats.last_active().clone(); - let Some(pointer) = seat.get_pointer() else { - return; - }; - let time = InputTime::now(); - for button in buttons { - let serial = SERIAL_COUNTER.next_serial(); - pointer.button( - self, - &smithay::input::pointer::ButtonEvent { - button, - state: smithay::backend::input::ButtonState::Released, - serial, - time, - }, - ); - } - pointer.frame(self); - } - - /// 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, 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); - } - } - - /// Send the seat's current modifier state to a single libei connection, used when that - /// connection's `ei_keyboard` device is created. The EI spec expects the current (nonzero) - /// modifier state to be announced once the device is live, so the client doesn't have to - /// wait for the next change to learn e.g. that Caps Lock is on. - pub(crate) fn send_ei_keyboard_modifiers( - &self, - conn: &smithay::reexports::reis::eis::Connection, - ) { - let Some(ei_seat) = self.common.ei_seats.get(conn) else { - return; - }; - let mods = { - let shell = self.common.shell.read(); - shell - .seats - .last_active() - .get_keyboard() - .map(|keyboard| keyboard.modifier_state().serialized) - }; - if let Some(s) = mods { - ei_seat.keyboard_modifiers(s.depressed, s.locked, s.latched, s.layout_effective); - } - } - - pub(crate) fn process_keyboard_filter( - &mut self, - backend_id: &InputBackendId, - seat: &Seat, - modifiers: &ModifiersState, - handle: KeysymHandle<'_>, - serial: Serial, - 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.get_keyboard().unwrap()); - } - - let current_focus = seat.get_keyboard().unwrap().current_focus(); - let shortcuts_inhibited = current_focus.as_ref().is_some_and(|f| { - f.wl_surface() - .map(|surface| { - seat.keyboard_shortcuts_inhibitor_for_surface(&surface) - .map(|inhibitor| inhibitor.is_active()) - .unwrap_or(false) - || seat.has_active_xwayland_grab(&surface) - }) - .unwrap_or(false) - }); - let sym = handle.modified_sym(); - - let result = self.filter_keyboard_input( - backend_id, seat, modifiers, handle, serial, keycode, key_state, time, - ); - - // A modifier-only binding fires on the modifier's release, but its press was already - // forwarded. Forward the release too. - if key_state == KeyState::Released - && matches!(&result, FilterResult::Intercept(Some((_, binding))) if binding.key.is_none()) - { - seat.get_keyboard().unwrap().input_forward( - self, - keycode, - key_state, - serial, - time, - previous_modifiers != *modifiers, - ); - } - - if (matches!(result, FilterResult::Forward) - && !seat.get_keyboard().unwrap().is_grabbed() - && !shortcuts_inhibited - && !matches!(current_focus, Some(KeyboardFocusTarget::LockSurface(_)))) - // we don't want to accidentally leave any keys pressed - || key_state == KeyState::Released - { - self.common - .xwayland_notify_key_event(sym, keycode, key_state, *modifiers, serial, time); - } - - result - } - - /// Inject a key from an auxiliary source (a virtual keyboard, or libei) into the shared - /// seat keyboard, tagged with `source` so its held keys are tracked independently of the - /// physical keyboard - /// - /// `handle_shortcuts` is `false` when synthesizing releases so still-held keys are just - /// forwarded without re-triggering bindings. - pub(crate) fn inject_source_key( - &mut self, - source: KeyboardSource, - backend_id: &InputBackendId, - seat: &Seat, - keycode: Keycode, - key_state: KeyState, - handle_shortcuts: bool, - ) { - let Some(keyboard) = seat.get_keyboard() else { - return; - }; - let serial = SERIAL_COUNTER.next_serial(); - let time = InputTime::now(); - let previous_modifiers = keyboard.modifier_state(); - let result = keyboard - .input_from_source( - source, - self, - keycode, - key_state, - serial, - time, - |data, modifiers, handle| { - if handle_shortcuts { - data.process_keyboard_filter( - backend_id, - seat, - modifiers, - handle, - serial, - time, - keycode, - key_state, - previous_modifiers, - ) - } else { - FilterResult::Forward - } - }, - ) - .flatten(); - - if let Some((action, pattern)) = result { - self.handle_action(action, backend_id, seat, serial, time, pattern, None); - } - } - - /// Inject a real key from a libei connection's `ei_keyboard` into the shared seat keyboard, - /// tagged with the connection's source so it behaves like any other keyboard (its keycodes - /// are interpreted with the seat keymap, which the compositor already forced onto the - /// `ei_keyboard` device). - pub(crate) fn inject_ei_key( - &mut self, - conn: &smithay::reexports::reis::eis::Connection, - keycode: Keycode, - key_state: KeyState, - ) { - let seat = self.common.shell.read().seats.last_active().clone(); - let backend_id = InputBackendId::Ei(conn.clone()); - let Some(source) = self.common.ei_keyboard_source.get(conn).copied() else { - return; - }; - self.inject_source_key(source, &backend_id, &seat, keycode, key_state, true); - } - - /// Inject a keysym from a libei `ei_text` device. - pub(crate) fn inject_ei_text_keysym( - &mut self, - conn: &smithay::reexports::reis::eis::Connection, - keysym: u32, - key_state: KeyState, - ) { - use smithay::wayland::input_method::InputMethodSeat; - use smithay::wayland::text_input::TextInputSeat; - - let keysym = Keysym::new(keysym); - - // `ei_text` is a tap: act on the press, ignore the release. - if key_state != KeyState::Pressed { - return; - } - let seat = self.common.shell.read().seats.last_active().clone(); - let Some(keyboard) = seat.get_keyboard() else { - return; - }; - - let mods = keyboard.modifier_state(); - let no_mods = !(mods.ctrl || mods.alt || mods.shift || mods.logo); - - // Is this keysym plain text, or not (Escape, F-keys, arrows, ...)? - let is_text = keysym.key_char().is_some_and(|c| !c.is_control()); - - // Resolve to a real keycode and feed it through the shared seat when this is *not* plain - // text, or when a modifier is held. - if !is_text || !no_mods { - if let Some(keycode) = keyboard.keycode_for_keysym(keysym) - && let Some(source) = self.common.ei_keyboard_source.get(conn).copied() - { - let backend_id = InputBackendId::Ei(conn.clone()); - self.inject_source_key( - source, - &backend_id, - &seat, - keycode, - KeyState::Pressed, - true, - ); - self.inject_source_key( - source, - &backend_id, - &seat, - keycode, - KeyState::Released, - true, - ); - return; - } - // No keycode for this keysym in the seat keymap (out-of-layout / Unicode), so fall - // through to the text paths below. Any held modifier is lost — best effort. - tracing::warn!( - "[ei-text] -> keysym not in seat keymap; falling back (modifier not applied)" - ); - } - - // No modifier held: a printable, non-control character committed directly through the - // text-input protocol when a text-input client is focused (and no real IME). This also - // covers out-of-layout / Unicode that has no keycode. - if no_mods - && is_text - && let Some(c) = keysym.key_char() - && !seat.input_method().has_instance() - { - let text_input = seat.text_input(); - let mut handled = false; - text_input.with_active_text_input(|ti, _surface| { - ti.commit_string(Some(c.to_string())); - handled = true; - }); - if handled { - text_input.done(false); - return; - } - } - - // Otherwise inject the keysym as a keycode tap via a temporary keymap delivered to just - // the focused client (reaches non-text-input apps: terminals, games, ...). This never - // touches the seat's own keyboard state. - keyboard.inject_text_keysyms(self, &[keysym]); - } - /// Determine is key event should be intercepted as a key binding, or forwarded to surface #[profiling::function] - pub fn filter_keyboard_input( + pub fn filter_keyboard_input>( &mut self, - backend_id: &InputBackendId, + event: &E, seat: &Seat, modifiers: &ModifiersState, handle: KeysymHandle<'_>, serial: Serial, - keycode: Keycode, - key_state: KeyState, - time: InputTime, ) -> FilterResult> { // Pre-compute for layout-agnostic shortcut matching let raw_syms = handle.raw_syms(); @@ -2306,15 +1636,12 @@ impl State { let keyboard = seat.get_keyboard().unwrap(); let pointer = seat.get_pointer().unwrap(); - // Escape only cancels grabs the compositor started for its own interactions - // For keyboard: SwapWindowGrab - // For pointer: MoveGrab, ResizeGrab, and MenuGrab - let keyboard_grabbed = - keyboard.with_grab(|_serial, grab| grab.is::()) == Some(true); - let pointer_grabbed = pointer.with_grab(|_serial, grab| { - grab.is::() || grab.is::() || grab.is::() + // We're only interested in filtering keyboard grabs if we initiated them. + // The easiest way to check that is to check the type of the grab. + let keyboard_grabbed = keyboard.with_grab(|_serial, grab| { + grab.is::() || grab.is::>() }) == Some(true); - let is_grabbed = keyboard_grabbed || pointer_grabbed; + let is_grabbed = keyboard_grabbed || pointer.is_grabbed(); let current_focus = keyboard.current_focus(); //this should fall back to active output since there may not be a focused output @@ -2332,7 +1659,7 @@ impl State { }); if let Some(a11y_keyboard_monitor) = self.common.dbus_state.a11y_keyboard_monitor() { - a11y_keyboard_monitor.key_event(modifiers, &handle, key_state); + a11y_keyboard_monitor.key_event(modifiers, &handle, event.state()); } // Leave move overview mode, if any modifier was released @@ -2354,7 +1681,7 @@ impl State { || (action_pattern.modifiers.shift && !modifiers.shift) || (action_pattern.key.is_some() && key_matches(action_pattern.key.unwrap()) - && key_state == KeyState::Released)) + && event.state() == KeyState::Released)) { shell.set_overview_mode(None, self.common.event_loop_handle.clone()); @@ -2370,7 +1697,7 @@ impl State { // Leave or update resize mode, if modifiers changed or initial key was released if let Some(action_pattern) = shell.resize_mode().0.active_binding() { if action_pattern.key.is_some() - && key_state == KeyState::Released + && event.state() == KeyState::Released && key_matches(action_pattern.key.unwrap()) { shell.set_resize_mode( @@ -2423,7 +1750,7 @@ impl State { let action = Action::Private(PrivateAction::Resizing( direction, edge.into(), - cosmic_keystate_from_smithay(key_state), + cosmic_keystate_from_smithay(event.state()), )); let key_pattern = shortcuts::Binding { modifiers: cosmic_modifiers_from_smithay(*modifiers), @@ -2432,8 +1759,8 @@ impl State { description: None, }; - if key_state == KeyState::Released { - if let Some(tokens) = seat.supressed_keys().filter(backend_id, &handle) { + if event.state() == KeyState::Released { + if let Some(tokens) = seat.supressed_keys().filter(&handle) { for token in tokens { self.common.event_loop_handle.remove(token); } @@ -2442,8 +1769,8 @@ impl State { let seat_clone = seat.clone(); let action_clone = action.clone(); let key_pattern_clone = key_pattern.clone(); - let backend_id_clone = backend_id.clone(); let start = Instant::now(); + let time = event.time_msec(); let token = self .common .event_loop_handle @@ -2453,12 +1780,9 @@ impl State { let duration = current.duration_since(start).as_millis(); state.handle_action( action_clone.clone(), - &backend_id_clone, &seat_clone, serial, - InputTime::from_millis( - time.millis().overflowing_add(duration as u32).0, - ), + time.overflowing_add(duration as u32).0, key_pattern_clone.clone(), None, ); @@ -2467,7 +1791,7 @@ impl State { ) .ok(); - seat.supressed_keys().add(backend_id, &handle, token); + seat.supressed_keys().add(&handle, token); } return FilterResult::Intercept(Some((action, key_pattern))); } @@ -2478,13 +1802,13 @@ impl State { // cancel grabs if is_grabbed && handle.modified_sym() == Keysym::Escape - && key_state == KeyState::Pressed + && event.state() == KeyState::Pressed && !modifiers.alt && !modifiers.ctrl && !modifiers.logo && !modifiers.shift { - seat.supressed_keys().add(backend_id, &handle, None); + seat.supressed_keys().add(&handle, None); return FilterResult::Intercept(Some(( Action::Private(PrivateAction::Escape), shortcuts::Binding { @@ -2497,7 +1821,7 @@ impl State { } if let Some(mut a11y_keyboard_monitor) = self.common.dbus_state.a11y_keyboard_monitor() { - if key_state == KeyState::Released { + if event.state() == KeyState::Released { let removed = a11y_keyboard_monitor.remove_active_virtual_mod(handle.modified_sym()); // If `Caps_Lock` is a virtual modifier, and is in locked state, clear it @@ -2506,11 +1830,11 @@ impl State { && (modifiers.serialized.locked & 2) != 0 { let seat = seat.clone(); - let key_code = keycode; + let key_code = event.key_code(); self.common.event_loop_handle.insert_idle(move |state| { if let Some(keyboard) = seat.get_keyboard() { let serial = SERIAL_COUNTER.next_serial(); - let time = InputTime::now(); + let time = state.common.clock.now().as_millis(); keyboard.input( state, key_code, @@ -2531,7 +1855,7 @@ impl State { } }); } - } else if key_state == KeyState::Pressed + } else if event.state() == KeyState::Pressed && a11y_keyboard_monitor.has_virtual_mod(handle.modified_sym()) { a11y_keyboard_monitor.add_active_virtual_mod(handle.modified_sym()); @@ -2540,15 +1864,15 @@ impl State { "active virtual mods: {:?}", a11y_keyboard_monitor.active_virtual_mods() ); - seat.supressed_keys().add(backend_id, &handle, None); + seat.supressed_keys().add(&handle, None); return FilterResult::Intercept(None); } } // Skip released events for initially surpressed keys - if key_state == KeyState::Released - && let Some(tokens) = seat.supressed_keys().filter(backend_id, &handle) + if event.state() == KeyState::Released + && let Some(tokens) = seat.supressed_keys().filter(&handle) { for token in tokens { self.common.event_loop_handle.remove(token); @@ -2557,7 +1881,7 @@ impl State { } // Handle VT switches - if key_state == KeyState::Pressed + if event.state() == KeyState::Pressed && (Keysym::XF86_Switch_VT_1.raw()..=Keysym::XF86_Switch_VT_12.raw()) .contains(&handle.modified_sym().raw()) { @@ -2566,18 +1890,18 @@ impl State { ) { error!(?err, "Failed switching virtual terminal."); } - seat.supressed_keys().add(backend_id, &handle, None); + seat.supressed_keys().add(&handle, None); return FilterResult::Intercept(None); } if let Some(a11y_keyboard_monitor) = self.common.dbus_state.a11y_keyboard_monitor() - && key_state == KeyState::Pressed + && event.state() == KeyState::Pressed && (a11y_keyboard_monitor.has_keyboard_grab() || a11y_keyboard_monitor.has_key_grab(modifiers, handle.modified_sym())) { let modifiers_queue = seat.modifiers_shortcut_queue(); - modifiers_queue.clear(backend_id); - seat.supressed_keys().add(backend_id, &handle, None); + modifiers_queue.clear(); + seat.supressed_keys().add(&handle, None); return FilterResult::Intercept(None); } @@ -2593,11 +1917,11 @@ impl State { // is this a released (triggered) modifier-only binding? if binding.key.is_none() - && key_state == KeyState::Released + && event.state() == KeyState::Released && !cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers) - && modifiers_queue.take(backend_id, binding) + && modifiers_queue.take(binding) { - modifiers_queue.clear(backend_id); + modifiers_queue.clear(); return FilterResult::Intercept(Some(( Action::Shortcut(action.clone()), binding.clone(), @@ -2606,21 +1930,21 @@ impl State { // could this potentially become a modifier-only binding? if binding.key.is_none() - && key_state == KeyState::Pressed + && event.state() == KeyState::Pressed && cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers) { - modifiers_queue.set(backend_id, binding.clone()); + modifiers_queue.set(binding.clone()); clear_queue = false; } // is this a normal binding? if binding.key.is_some() - && key_state == KeyState::Pressed + && event.state() == KeyState::Pressed && key_matches(binding.key.unwrap()) && cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers) { - modifiers_queue.clear(backend_id); - seat.supressed_keys().add(backend_id, &handle, None); + modifiers_queue.clear(); + seat.supressed_keys().add(&handle, None); return FilterResult::Intercept(Some(( Action::Shortcut(action.clone()), binding.clone(), @@ -2631,7 +1955,7 @@ impl State { // no binding if clear_queue { - seat.modifiers_shortcut_queue().clear(backend_id); + seat.modifiers_shortcut_queue().clear(); } // keys are passed through to apps FilterResult::Forward @@ -3036,7 +2360,6 @@ impl State { surface: &WlSurface, pointer: &PointerHandle, mut location: Point, - constraint: Option<&PointerConstraint>, ) { let Some(client) = surface.client() else { return; @@ -3061,13 +2384,15 @@ impl State { return false; } - 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 + 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 + }) }; let workspace_origin = output.geometry().loc.to_f64(); @@ -3091,23 +2416,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 = InputTime::now(); + let time = self.common.clock.now(); pointer.relative_motion( self, under.clone(), &RelativeMotionEvent { delta: (0., 0.).into(), delta_unaccel: (0., 0.).into(), - time, + utime: time.as_micros(), }, ); pointer.motion( self, under, - &PointerMotionEvent { + &MotionEvent { location: point.as_logical(), serial, - time, + time: time.as_millis(), }, ); pointer.frame(self); @@ -3204,7 +2529,7 @@ pub fn update_output_image_copy_cursor_position( position: Point, ) { let output_geometry = output.geometry(); - for session in cursor_sessions_for_output(shell, output) { + for session in cursor_sessions_for_output(&shell, &output) { if let Some(cursor_geometry) = seat.cursor_geometry( (position - output_geometry.loc.to_f64()) .as_logical() diff --git a/src/input/tablet_emu.rs b/src/input/tablet_emu.rs deleted file mode 100644 index 6ab17924..00000000 --- a/src/input/tablet_emu.rs +++ /dev/null @@ -1,256 +0,0 @@ -// 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/lib.rs b/src/lib.rs index 98bfa2a3..542162eb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ use smithay::{ }; use anyhow::{Context, Result}; -use state::{BackendData, LastRefresh, State}; +use state::{LastRefresh, State}; use std::{ env, ffi::OsString, @@ -43,7 +43,6 @@ pub mod dbus; pub mod debug; pub mod hooks; pub mod input; -pub mod libei; mod logger; pub mod session; pub mod shell; @@ -177,10 +176,6 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { with_xwayland, kiosk_command, ); - // Set up the libei sender side before the backend spawns Xwayland. - let ei_sender = libei::setup_ei(&event_loop.handle()); - state.common.dbus_state.set_ei_sender(ei_sender); - // init backend backend::init_backend_auto(&display, &mut event_loop, &mut state)?; @@ -227,17 +222,19 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { // Kiosk child exited with status Ok(Some(exit_status)) => { info!("Command exited with status {:?}", exit_status); - // Stop cleanly so surface threads are joined before exit() (signal -> 1). - state.common.kiosk_exit_code = Some(exit_status.code().unwrap_or(1)); - state.common.should_stop = true; + match exit_status.code() { + // Exiting with the same status as the kiosk child + Some(code) => process::exit(code), + // The kiosk child exited with signal, exiting with error + None => process::exit(1), + } } // Command still running Ok(None) => {} // Kiosk child disappeared, exiting with error Err(err) => { warn!(?err, "Failed to wait for command"); - state.common.kiosk_exit_code = Some(1); - state.common.should_stop = true; + process::exit(1); } } } @@ -248,32 +245,10 @@ pub fn run(hooks: crate::hooks::Hooks) -> Result<(), Box> { let _ = child.kill(); } - let kiosk_exit_code = state.common.kiosk_exit_code; - - // Join surface threads before exit() so no thread is mid-eglCreateSync when - // Mesa's atexit handlers run and corrupt the heap (issue #2375). Safe here - // because the event loop has stopped; an unconditional join in Surface::Drop - // would instead deadlock against apply_config_for_outputs. - if let BackendData::Kms(kms) = &mut state.backend { - // Release master first so the surface drop path skips its blocking commit. - for device in kms.drm_devices.values_mut() { - device.drm.pause(); - } - for device in kms.drm_devices.values_mut() { - for (_, surface) in device.inner.surfaces.drain() { - surface.drop_and_join(); - } - } - } - // drop eventloop & state before logger std::mem::drop(event_loop); std::mem::drop(state); - if let Some(code) = kiosk_exit_code { - process::exit(code); - } - Ok(()) } @@ -289,7 +264,7 @@ Project home page: https://github.com/pop-os/cosmic-comp Options: -h, --help Show this message --no-xwayland Run without Xwayland - -V, --version Show the version of cosmic-comp"# + -v, --version Show the version of cosmic-comp"# ); } diff --git a/src/libei.rs b/src/libei.rs deleted file mode 100644 index 487f0387..00000000 --- a/src/libei.rs +++ /dev/null @@ -1,230 +0,0 @@ -use std::os::unix::net::UnixStream; - -use reis::eis; -use smithay::reexports::reis; - -use smithay::backend::libei::{EiInput, EiInputEvent, EiRegion}; -use smithay::input::keyboard::Keysym; -use smithay::reexports::calloop; -use smithay::wayland::input_method::InputMethodSeat; -use smithay::wayland::text_input::TextInputSeat; - -use crate::config::xkb_config_to_wl; -use crate::input::InputBackendId; -use crate::state::{BackendData, State}; -use crate::utils::{geometry::RectGlobalExt, prelude::OutputExt}; - -// Requested device types for an EI connection, mirroring the XDG RemoteDesktop portal `DeviceType` bitmask -const DEVICE_TYPE_KEYBOARD: u32 = 1; -const DEVICE_TYPE_POINTER: u32 = 2; -const DEVICE_TYPE_TOUCHSCREEN: u32 = 4; - -// Name of the EI absolute-pointer device. Shared so the connect path and the -// re-advertise-on-output-change path recreate the same device. -const ABSOLUTE_POINTER_NAME: &str = "virtual absolute pointer"; - -pub type EiRequest = (UnixStream, u32); - -/// Build the regions advertised on the EI absolute devices (absolute pointer and touch) for the -/// output layout: one region per output, each at its **global logical** offset with -/// its logical size and scale. -pub fn absolute_regions(state: &State) -> Vec { - let shell = state.common.shell.read(); - shell - .outputs() - .map(|output| { - let scale = output.current_scale().fractional_scale(); - EiRegion { - // Keep the signed logical rect - // the u32 clamp happens at the `ei_device.region` in smithay. - rect: output.geometry().as_logical(), - scale: scale as f32, - // Tie the region to its output so a client can correlate it with the - // matching screencast stream (the portal advertises the same name). - mapping_id: Some(output.name()), - } - }) - .collect() -} - -/// Re-advertise the coordinate regions on every active EI seat's absolute devices. -pub fn refresh_absolute_pointer_regions(state: &State) { - if state.common.ei_seats.is_empty() { - return; - } - let regions = absolute_regions(state); - for seat in state.common.ei_seats.values() { - seat.update_regions(®ions); - } -} - -pub fn setup_ei( - handle: &calloop::LoopHandle<'static, State>, -) -> calloop::channel::Sender { - let (sender, channel) = calloop::channel::channel::(); - let handle_clone = handle.clone(); - handle - .insert_source(channel, move |event, _, _| { - let calloop::channel::Event::Msg((stream, device_types)) = event else { - return; - }; - let context = match eis::Context::new(stream) { - Ok(context) => context, - Err(err) => { - tracing::error!("Failed to create EI context: {}", err); - return; - } - }; - let source = EiInput::new(context); - if let Err(err) = - handle_clone.insert_source(source, move |event, connection, data| match event { - EiInputEvent::Connected => { - let conn = connection.eis_connection().clone(); - let seat = connection.add_seat("default"); - let wants_keyboard = device_types & DEVICE_TYPE_KEYBOARD != 0; - if wants_keyboard { - let conf = data.common.config.xkb_config(); - // The ei_keyboard device is given the compositor keymap; its key - // events feed the shared seat like any other keyboard. - let _ = seat.add_keyboard("virtual keyboard", xkb_config_to_wl(&conf)); - // The text device lets clients inject keysyms/utf8 directly, delivered - seat.add_text("virtual text"); - } - if device_types & DEVICE_TYPE_POINTER != 0 { - seat.add_pointer("virtual pointer"); - let regions = absolute_regions(data); - seat.add_pointer_absolute(ABSOLUTE_POINTER_NAME, ®ions); - } - if device_types & DEVICE_TYPE_TOUCHSCREEN != 0 { - let regions = absolute_regions(data); - seat.add_touch("virtual touch", ®ions); - } - // Kb-capable connections get a shared-seat source so their `ei_keyboard` - // key events feed the seat keyboard tracking. - if wants_keyboard { - data.common.ei_keyboard_source.insert( - conn.clone(), - smithay::input::keyboard::KeyboardSource::new_auxiliary(), - ); - } - // Track the seat for every connection - data.common.ei_seats.insert(conn, seat); - data.update_ei_input_method(); - } - EiInputEvent::Disconnected => { - let conn = connection.eis_connection().clone(); - let backend_id = InputBackendId::Ei(conn.clone()); - // Release any keys/modifiers and pointer buttons this remote still holds - data.release_ei_keyboard(&conn); - data.release_ei_pointer(&conn); - data.clear_input_source_state(&backend_id); - data.common.ei_seats.remove(&conn); - data.common.ei_keyboard_source.remove(&conn); - data.common.ei_pointer_buttons.remove(&conn); - 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(); - if let Some(keyboard) = seat.get_keyboard() { - data.broadcast_ei_keyboard_modifiers(&keyboard); - } - } - EiInputEvent::Event(event) => { - use smithay::backend::input::{InputEvent, KeyboardKeyEvent}; - match event { - InputEvent::Keyboard { event } => { - data.inject_ei_key( - connection.eis_connection(), - event.key_code(), - event.state(), - ); - } - other => { - let backend_id = - InputBackendId::Ei(connection.eis_connection().clone()); - data.process_input_event(other, backend_id); - if matches!(data.backend, BackendData::Kms(_)) { - for output in data.common.shell.read().outputs() { - data.backend.kms().schedule_render(output); - } - } - } - } - } - EiInputEvent::TextKeysym { keysym, state } => { - data.inject_ei_text_keysym(connection.eis_connection(), keysym, state); - } - EiInputEvent::TextUtf8 { text } => { - data.inject_ei_text(&text); - } - }) - { - tracing::error!("Failed to insert EI input source: {}", err); - } - }) - .expect("Failed to insert EI channel source into the event loop"); - - sender -} - -impl State { - /// Act as the input method for text injection while any text-capable EI connection is - /// active, so `ei_text` UTF-8 can be committed into the focused app even without a real - /// IME, but only when none is bound (a real IME always wins) - pub(crate) fn update_ei_input_method(&mut self) { - let active = !self.common.ei_keyboard_source.is_empty(); - let seats = self - .common - .shell - .read() - .seats - .iter() - .cloned() - .collect::>(); - for seat in seats { - let has_ime = seat.input_method().has_instance(); - let text_input = seat.text_input(); - if active { - if !has_ime { - text_input.set_compositor_input_method(true); - } - } else { - text_input.set_compositor_input_method(false); - } - } - } - - /// Inject UTF-8 text (from an EI `ei_text` device) into the focused client. - pub fn inject_ei_text(&mut self, text: &str) { - let seat = self.common.shell.read().seats.last_active().clone(); - // Only commit through text-input when we're the active input method (no real IME) - if !seat.input_method().has_instance() { - let text_input = seat.text_input(); - let mut injected = false; - text_input.with_active_text_input(|ti, _surface| { - ti.commit_string(Some(text.to_owned())); - injected = true; - }); - if injected { - text_input.done(false); - return; - } - } - - // Bind the whole chunk to spare keycodes in one temporary keymap per batch (delivered - // to just the focused client), so we change the keymap ~once per chunk instead of once - // per character. Leaves the seat's own keyboard state untouched. - let keysyms: Vec = text - .chars() - .map(Keysym::from_char) - .filter(|keysym| keysym.raw() != 0) - .collect(); - let Some(keyboard) = seat.get_keyboard() else { - return; - }; - // At most ~247 keysyms fit one spare keymap (keycodes 9..=255); leave margin. - const BATCH: usize = 240; - for batch in keysyms.chunks(BATCH) { - keyboard.inject_text_keysyms(self, batch); - } - } -} diff --git a/src/main.rs b/src/main.rs index 7ae05991..ffa37236 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,15 @@ // SPDX-License-Identifier: GPL-3.0-only fn main() { + // libcosmic-yoda enables zbus' `tokio` feature, so zbus 5.14 expects an + // ambient Tokio runtime via Handle::current(). cosmic-comp's loop is not + // async, so hold a runtime guard for the lifetime of run(). + let runtime = tokio::runtime::Builder::new_multi_thread() + .enable_all() + .build() + .expect("failed to build tokio runtime"); + let _guard = runtime.enter(); + if let Err(err) = cosmic_comp::run(Default::default()) { tracing::error!("Error occured in main(): {}", err); std::process::exit(1); diff --git a/src/shell/element/mod.rs b/src/shell/element/mod.rs index d4743b7f..14736719 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::{InputTime, KeyState}, + input::KeyState, renderer::{ element::{ Element, Kind, RenderElement, UnderlyingStorage, @@ -1012,7 +1012,7 @@ impl KeyboardTarget for CosmicMapped { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: InputTime, + time: u32, ) { match &self.element { CosmicMappedInternal::Stack(s) => { diff --git a/src/shell/element/stack.rs b/src/shell/element/stack.rs index 7f7f6317..7ce26204 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::{GrabType, ReleaseMode, ResizeEdge}, + grabs::{ReleaseMode, ResizeEdge}, layout::tiling::NodeDesc, }, state::State, @@ -38,7 +38,7 @@ use shortcuts::action::{Direction, FocusDirection}; use smithay::{ backend::{ drm::DrmNode, - input::{InputTime, KeyState, TabletToolDescriptor}, + input::KeyState, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -52,23 +52,14 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorImageStatus, - GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, - GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, - GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + AxisFrame, ButtonEvent, CursorImageStatus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, - tablet::{ - Tablet, TabletSeatTrait, - tool::{ - AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, - DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, - UpEvent as ToolUpEvent, - }, - }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, + DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, + TouchTarget, UpEvent, }, }, output::Output, @@ -121,7 +112,6 @@ pub struct CosmicStackInternal { previous_keyboard: AtomicUsize, pointer_entered: AtomicU8, touch_serial: AtomicU32, - tablet_serial: AtomicU32, reenter: AtomicBool, potential_drag: Mutex>, override_alive: AtomicBool, @@ -181,7 +171,6 @@ 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), @@ -842,7 +831,7 @@ impl CosmicStack { ))); }; - let radii = radii.map(|[_, _, c, d]| [0, 0, c, d]); + let radii = radii.map(|[a, _, c, _]| [a, 0, c, 0]); windows[active].push_render_elements( renderer, window_loc, @@ -920,19 +909,12 @@ impl CosmicStack { false, ); if let Some((grab, focus)) = res { - match grab.grab_type() { - GrabType::Touch => { - seat.get_touch().unwrap().set_grab(state, grab, serial) - } - GrabType::Pointer => seat - .get_pointer() + 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), - GrabType::TabletTool => seat - .tablet_seat() - .get_tool(grab.tool().unwrap()) - .unwrap() - .set_grab(state, grab, InputTime::now(), serial, focus), + .set_grab(state, grab, serial, focus); } } }); @@ -1015,17 +997,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]; + corners[0] = radii[0].max(corners[0]); corners[1] = radii[1]; corners[2] = radii[2].max(corners[2]); - corners[3] = radii[3].max(corners[3]); + corners[3] = radii[3]; corners } @@ -1107,19 +1089,12 @@ impl Program for CosmicStackInternal { false, ); if let Some((grab, focus)) = res { - match grab.grab_type() { - GrabType::Touch => { - seat.get_touch().unwrap().set_grab(state, grab, serial) - } - GrabType::Pointer => seat - .get_pointer() + 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), - GrabType::TabletTool => seat - .tablet_seat() - .get_tool(grab.tool().unwrap()) - .unwrap() - .set_grab(state, grab, InputTime::now(), serial, focus), + .set_grab(state, grab, serial, focus); } } }); @@ -1572,7 +1547,7 @@ impl KeyboardTarget for CosmicStack { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: InputTime, + time: u32, ) { let active = self.keyboard_leave_if_previous(seat, data, serial); self.0.with_program(|p| { @@ -1612,7 +1587,7 @@ impl KeyboardTarget for CosmicStack { } impl PointerTarget for CosmicStack { - fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active_window = &p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)]; @@ -1640,7 +1615,7 @@ impl PointerTarget for CosmicStack { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let active = p.active.load(Ordering::SeqCst); @@ -1683,7 +1658,7 @@ impl PointerTarget for CosmicStack { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1714,12 +1689,14 @@ impl PointerTarget for CosmicStack { state.common.config.cosmic_conf.edge_snap_threshold, false, ); - if let Some((grab, focus)) = res - && let GrabType::Pointer = grab.grab_type() - { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus); + 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); + } } }); } @@ -1727,7 +1704,7 @@ impl PointerTarget for CosmicStack { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1739,7 +1716,7 @@ impl PointerTarget for CosmicStack { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { self.0.with_program(|p| { let mut cursor_state = seat .user_data() @@ -1775,12 +1752,14 @@ impl PointerTarget for CosmicStack { &state.common.event_loop_handle, false, ); - if let Some((grab, focus)) = res - && let GrabType::Pointer = grab.grab_type() - { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus); + 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); + } } }); } @@ -1853,7 +1832,7 @@ impl PointerTarget for CosmicStack { } impl TouchTarget for CosmicStack { - fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { let mut event = event.clone(); let active_window_geo = self.0.with_program(|p| { p.windows.lock().unwrap()[p.active.load(Ordering::SeqCst)].geometry() @@ -1864,7 +1843,7 @@ impl TouchTarget for CosmicStack { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1912,185 +1891,6 @@ 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 5613f76e..1a311dfc 100644 --- a/src/shell/element/stack/tab.rs +++ b/src/shell/element/stack/tab.rs @@ -8,7 +8,6 @@ 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}, @@ -371,7 +370,6 @@ 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); @@ -390,7 +388,6 @@ 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 9dd5ef81..86218db6 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, VecDeque}, + collections::{HashMap, HashSet, VecDeque}, time::{Duration, Instant}, }; @@ -757,10 +757,12 @@ where state.last_state = Some(current_state.clone()); } let last_state = state.last_state.as_mut().unwrap(); - let unknown_keys = current_state.len() != last_state.len() - || current_state - .keys() - .any(|key| !last_state.contains_key(key)); + let unknown_keys = current_state + .keys() + .collect::>() + .symmetric_difference(&last_state.keys().collect::>()) + .next() + .is_some(); enum Difference { NewOrRemoved, diff --git a/src/shell/element/surface.rs b/src/shell/element/surface.rs index a7fd922d..e146efeb 100644 --- a/src/shell/element/surface.rs +++ b/src/shell/element/surface.rs @@ -21,7 +21,6 @@ use std::{ use smithay::{ backend::{ drm::DrmNode, - input::InputTime, renderer::{ ImportAll, Renderer, buffer_has_alpha, element::{Kind, RenderElementStates, surface::KindEvaluation}, @@ -839,7 +838,10 @@ impl CosmicSurface { self.0 .send_dmabuf_feedback(output, primary_scan_out_output, |_, data| { if is_fullscreen { - &feedback.primary_scanout_feedback + feedback + .primary_scanout_feedback + .as_ref() + .unwrap_or(&feedback.render_feedback) } else if frame_time_filter_fn(data) == Kind::ScanoutCandidate { feedback .overlay_scanout_feedback @@ -1085,7 +1087,7 @@ impl KeyboardTarget for CosmicSurface { key: KeysymHandle<'_>, state: smithay::backend::input::KeyState, serial: smithay::utils::Serial, - time: InputTime, + time: u32, ) { match self.0.underlying_surface() { WindowSurface::Wayland(toplevel) => { diff --git a/src/shell/element/window.rs b/src/shell/element/window.rs index c06609fe..838efd24 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::{GrabType, ReleaseMode, ResizeEdge}, + grabs::{ReleaseMode, ResizeEdge}, }, state::State, utils::{ @@ -21,7 +21,7 @@ use cosmic_comp_config::AppearanceConfig; use smithay::{ backend::{ drm::DrmNode, - input::{InputTime, KeyState, TabletToolDescriptor}, + input::KeyState, renderer::{ ImportAll, ImportMem, Renderer, element::{Element, Id as RendererId, Kind, RenderElement, UnderlyingStorage}, @@ -35,23 +35,14 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, CursorIcon, CursorImageStatus, GestureHoldBeginEvent, + GestureHoldEndEvent, GesturePinchBeginEvent, GesturePinchEndEvent, + GesturePinchUpdateEvent, GestureSwipeBeginEvent, GestureSwipeEndEvent, + GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, + DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, + TouchTarget, UpEvent, }, }, output::Output, @@ -438,12 +429,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; } } @@ -510,12 +501,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; } } @@ -560,8 +551,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 { @@ -585,8 +576,8 @@ impl CosmicWindow { }); if has_ssd { + radii[0] = 0; radii[2] = 0; - radii[3] = 0; let ssd_loc = location + self .0 @@ -691,26 +682,26 @@ impl CosmicWindow { (has_ssd, true) => { let mut corners = p.window.corner_radius(geometry_size).unwrap_or(radii); - corners[0] = if has_ssd { - radii[0] - } else { - radii[0].max(corners[0]) - }; + corners[0] = 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] = radii[3].max(corners[3]); + corners[3] = if has_ssd { + radii[3] + } else { + radii[3].max(corners[3]) + }; corners } (true, false) => p .window .corner_radius(geometry_size) - .map(|[_, _, c, d]| [radii[0], radii[1], c, d]) - .unwrap_or([radii[0], radii[1], default_radius, default_radius]), + .map(|[a, _, c, _]| [a, radii[1], c, radii[3]]) + .unwrap_or([default_radius, radii[1], default_radius, radii[3]]), (false, false) => p .window .corner_radius(geometry_size) @@ -755,19 +746,12 @@ impl Program for CosmicWindowInternal { false, ); if let Some((grab, focus)) = res { - match grab.grab_type() { - GrabType::Touch => { - seat.get_touch().unwrap().set_grab(state, grab, serial) - } - GrabType::Pointer => seat - .get_pointer() + 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), - GrabType::TabletTool => seat - .tablet_seat() - .get_tool(grab.tool().unwrap()) - .unwrap() - .set_grab(state, grab, InputTime::now(), serial, focus), + .set_grab(state, grab, serial, focus); } } }); @@ -997,7 +981,7 @@ impl KeyboardTarget for CosmicWindow { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: InputTime, + time: u32, ) { self.0 .with_program(|p| KeyboardTarget::key(&p.window, seat, data, key, state, serial, time)) @@ -1015,7 +999,7 @@ impl KeyboardTarget for CosmicWindow { } impl PointerTarget for CosmicWindow { - fn enter(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + fn enter(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1028,7 +1012,8 @@ impl PointerTarget for CosmicWindow { return; }; - let _ = p.swap_focus(Some(next)); + let old_focus = p.swap_focus(Some(next)); + assert_eq!(old_focus, None); let cursor_state = seat.user_data().get::().unwrap(); cursor_state.lock().unwrap().set_shape(next.cursor_shape()); @@ -1040,7 +1025,7 @@ impl PointerTarget for CosmicWindow { PointerTarget::enter(&self.0, seat, data, &event) } - fn motion(&self, seat: &Seat, data: &mut State, event: &PointerMotionEvent) { + fn motion(&self, seat: &Seat, data: &mut State, event: &MotionEvent) { let mut event = event.clone(); self.0.with_program(|p| { let has_ssd = p.has_ssd(false); @@ -1072,7 +1057,7 @@ impl PointerTarget for CosmicWindow { ) { } - fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { match self.0.with_program(|p| p.current_focus()) { Some(Focus::Header) => PointerTarget::button(&self.0, seat, data, event), Some(x) => { @@ -1108,12 +1093,14 @@ impl PointerTarget for CosmicWindow { false, ); - if let Some((grab, focus)) = res - && let GrabType::Pointer = grab.grab_type() - { - seat.get_pointer() - .unwrap() - .set_grab(state, grab, serial, focus) + 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); + } } }); } @@ -1121,7 +1108,7 @@ impl PointerTarget for CosmicWindow { } } - fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { if let Some(Focus::Header) = self.0.with_program(|p| p.current_focus()) { PointerTarget::axis(&self.0, seat, data, frame) } @@ -1133,7 +1120,7 @@ impl PointerTarget for CosmicWindow { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { self.0.with_program(|p| { let cursor_state = seat.user_data().get::().unwrap(); cursor_state.lock().unwrap().unset_shape(); @@ -1208,7 +1195,7 @@ impl PointerTarget for CosmicWindow { } impl TouchTarget for CosmicWindow { - fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { let mut event = event.clone(); self.0.with_program(|p| { event.location -= p.window.geometry().loc.to_f64(); @@ -1216,7 +1203,7 @@ impl TouchTarget for CosmicWindow { TouchTarget::down(&self.0, seat, data, &event) } - fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { TouchTarget::up(&self.0, seat, data, event) } @@ -1247,155 +1234,6 @@ 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 dcfd55de..4e88c499 100644 --- a/src/shell/focus/mod.rs +++ b/src/shell/focus/mod.rs @@ -2,18 +2,11 @@ use crate::{ shell::{CosmicSurface, MinimizedWindow, Shell, Trigger, element::CosmicMapped}, state::{Common, State}, utils::prelude::*, - wayland::{ - handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData}, - protocols::session_lock_layer::layer_show_on_lock, - }, + wayland::handlers::{xdg_shell::PopupGrabData, xwayland_keyboard_grab::XWaylandGrabSeatData}, }; use indexmap::IndexSet; use smithay::{ - backend::input::InputTime, - desktop::{ - LayerSurface, PopupUngrabStrategy, WindowSurfaceType, find_popup_root_surface, - layer_map_for_output, - }, + desktop::{PopupUngrabStrategy, layer_map_for_output}, input::{Seat, pointer::MotionEvent}, output::Output, reexports::wayland_server::{Resource, protocol::wl_surface::WlSurface}, @@ -219,29 +212,6 @@ impl Shell { state.common.shell.write().update_active(); } - // We suppress Element(X) to Fullscreen(X) transition to avoid - // loss of focus by the X window when having a transition to fullscreen - // but in the case of X11 unmap/map the leave/enter needs to happen for the X11 - // internal state to be focused on the window - pub fn set_focus_on_x11_map( - state: &mut State, - target: &KeyboardFocusTarget, - seat: &Seat, - update_cursor: bool, - ) { - let need_reset = seat - .get_keyboard() - .and_then(|keyboard| keyboard.current_focus()) - .and_then(|current| current.x11_surface()) - .is_some_and(|current| Some(current) == target.x11_surface()); - - if need_reset { - update_focus_state(seat, None, state, None, false); - } - - Shell::set_focus(state, Some(target), seat, None, update_cursor); - } - pub fn append_focus_stack(&mut self, target: impl Into, seat: &Seat) { let target = target.into(); if target.is_minimized() { @@ -426,7 +396,7 @@ fn update_focus_state( &MotionEvent { location: new_pos.as_logical(), serial: SERIAL_COUNTER.next_serial(), - time: InputTime::now(), + time: 0, }, ); } @@ -633,42 +603,19 @@ fn focus_target_is_valid( output: &Output, target: KeyboardFocusTarget, ) -> bool { - // If a session lock is active, only lock surfaces and lock layers can be focused + // If a session lock is active, only lock surfaces can be focused if shell.session_lock.is_some() { - if let KeyboardFocusTarget::LayerSurface(layer) = &target { - return layer_show_on_lock(layer.wl_surface()); - } else if let KeyboardFocusTarget::Popup(popup) = &target - && let Ok(root) = find_popup_root_surface(popup) - { - return layer_show_on_lock(&root); - } return matches!(target, KeyboardFocusTarget::LockSurface(_)); } // If an exclusive layer shell surface exists (on any output), only exclusive // shell surfaces can have focus, on the highest layer with exclusive surfaces. - // Popups are judged by their root surface, so an exclusive surface can - // still open grabbing popups (menus, dropdowns, context menus). if let Some(layer) = exclusive_layer_surface_layer(shell) { - let is_exclusive_on_layer = |layer_surface: &LayerSurface| { + return if let KeyboardFocusTarget::LayerSurface(layer_surface) = target { let data = layer_surface.cached_state(); (data.keyboard_interactivity, data.layer) == (KeyboardInteractivity::Exclusive, layer) - }; - return match target { - KeyboardFocusTarget::LayerSurface(layer_surface) => { - is_exclusive_on_layer(&layer_surface) - } - KeyboardFocusTarget::Popup(popup) => find_popup_root_surface(&popup) - .ok() - .and_then(|root| { - shell.outputs().find_map(|o| { - layer_map_for_output(o) - .layer_for_surface(&root, WindowSurfaceType::ALL) - .map(&is_exclusive_on_layer) - }) - }) - .unwrap_or(false), - _ => false, + } else { + false }; } @@ -798,7 +745,7 @@ fn update_pointer_focus(state: &mut State, seat: &Seat) { &MotionEvent { location: pointer.current_location(), serial: SERIAL_COUNTER.next_serial(), - time: InputTime::now(), + time: state.common.clock.now().as_millis(), }, ); } diff --git a/src/shell/focus/order.rs b/src/shell/focus/order.rs index 937fa311..fb904c01 100644 --- a/src/shell/focus/order.rs +++ b/src/shell/focus/order.rs @@ -22,7 +22,7 @@ use crate::{ prelude::OutputExt, quirks::{WORKSPACE_OVERVIEW_NAMESPACE, workspace_overview_is_open}, }, - wayland::protocols::{session_lock_layer::layer_show_on_lock, workspace::WorkspaceHandle}, + wayland::protocols::workspace::WorkspaceHandle, }; pub enum Stage<'a> { @@ -77,8 +77,6 @@ fn render_input_order_internal( element_filter: ElementFilter, mut callback: impl FnMut(Stage) -> ControlFlow, ()>, ) -> ControlFlow, ()> { - // NOTE: Keep in sync with other surface iteration functions - if shell .zoom_state .as_ref() @@ -89,92 +87,7 @@ fn render_input_order_internal( // Session Lock if let Some(session_lock) = &shell.session_lock { - for (layer, popup, location) in layer_popups(output, Layer::Overlay, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerPopup { - layer, - popup: &popup, - location, - workspace_idx: current.1, - })?; - } - for (layer, location) in layer_surfaces(output, Layer::Overlay, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerSurface { - layer, - location, - workspace_idx: current.1, - })?; - } - for (layer, popup, location) in layer_popups(output, Layer::Top, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerPopup { - layer, - popup: &popup, - location, - workspace_idx: current.1, - })?; - } - for (layer, location) in layer_surfaces(output, Layer::Top, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerSurface { - layer, - location, - workspace_idx: current.1, - })?; - } - callback(Stage::SessionLock(session_lock.surfaces.get(output)))?; - for (layer, popup, location) in layer_popups(output, Layer::Bottom, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerPopup { - layer, - popup: &popup, - location, - workspace_idx: current.1, - })?; - } - for (layer, popup, location) in layer_popups(output, Layer::Background, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerPopup { - layer, - popup: &popup, - location, - workspace_idx: current.1, - })?; - } - for (layer, location) in layer_surfaces(output, Layer::Bottom, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerSurface { - layer, - location, - workspace_idx: current.1, - })?; - } - for (layer, location) in layer_surfaces(output, Layer::Background, element_filter) { - if !layer_show_on_lock(layer.wl_surface()) { - continue; - } - callback(Stage::LayerSurface { - layer, - location, - workspace_idx: current.1, - })?; - } - return ControlFlow::Continue(()); + return callback(Stage::SessionLock(session_lock.surfaces.get(output))); } // Overlay-level layer shell diff --git a/src/shell/focus/target.rs b/src/shell/focus/target.rs index c914e0fa..929cd92e 100644 --- a/src/shell/focus/target.rs +++ b/src/shell/focus/target.rs @@ -16,30 +16,21 @@ use crate::{ }; use id_tree::NodeId; use smithay::{ - backend::input::{InputTime, KeyState, TabletToolDescriptor}, + backend::input::KeyState, desktop::{LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, space::SpaceElement}, input::{ Seat, dnd::{DndFocus, OfferData, Source}, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, + DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, + TouchTarget, UpEvent, }, }, reexports::wayland_server::{ @@ -173,17 +164,6 @@ 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, @@ -292,10 +272,9 @@ impl PointerFocusTarget { None }; - let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) = seat.cursor_geometry( - (0.0, 0.0), - Duration::from_millis(event.time.millis() as u64).into(), - ) { + let cursor_hotspot = if let Some(CursorGeometry { hotspot, .. }) = + seat.cursor_geometry((0.0, 0.0), Duration::from_millis(event.time as u64).into()) + { hotspot } else { Point::from((0, 0)) @@ -306,16 +285,6 @@ 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 { @@ -357,7 +326,7 @@ impl KeyboardFocusTarget { } } - pub fn x11_surface(&self) -> Option { + fn x11_surface(&self) -> Option { match self { KeyboardFocusTarget::Element(mapped) => mapped.active_window().x11_surface().cloned(), KeyboardFocusTarget::Fullscreen(surface) => surface.x11_surface().cloned(), @@ -439,16 +408,16 @@ impl PointerTarget for PointerFocusTarget { self.inner_pointer_target() .relative_motion(seat, data, event); } - fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { self.inner_pointer_target().button(seat, data, event); } - fn axis(&self, seat: &Seat, data: &mut State, frame: PointerAxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { 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: InputTime) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { let toplevel = self.toplevel(&data.common.shell.read()); if let Some(element) = toplevel { for session in element.cursor_sessions() { @@ -528,102 +497,12 @@ 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: &TouchDownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { self.inner_touch_target().down(seat, data, event); } - fn up(&self, seat: &Seat, data: &mut State, event: &TouchUpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { self.inner_touch_target().up(seat, data, event); } @@ -714,7 +593,7 @@ impl DndFocus for PointerFocusTarget { offer: Option<&mut CosmicOfferData>, seat: &Seat, location: Point, - time: InputTime, + time: u32, ) { match self { PointerFocusTarget::WlSurface { surface, .. } => { @@ -816,7 +695,7 @@ impl KeyboardTarget for KeyboardFocusTarget { key: KeysymHandle<'_>, state: KeyState, serial: Serial, - time: InputTime, + time: u32, ) { 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 ca19e4cb..96d33dc6 100644 --- a/src/shell/grabs/delay.rs +++ b/src/shell/grabs/delay.rs @@ -1,34 +1,22 @@ use smithay::{ - backend::input::{InputTime, TabletToolDescriptor}, input::{ Seat, SeatHandler, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab, + PointerInnerHandle, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, - MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, UpEvent as TouchUpEvent, + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, }, }, utils::{Logical, Point, SERIAL_COUNTER, Serial}, }; -use crate::{shell::grabs::GrabType, state::State}; +use crate::state::State; use super::GrabStartData; @@ -56,15 +44,10 @@ impl DelayGrab { } } - 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 + pub fn is_touch_grab(&self) -> bool { + match self.start_data { + GrabStartData::Touch(_) => true, + GrabStartData::Pointer(_) => false, } } } @@ -109,7 +92,7 @@ impl> PointerGrab for DelayGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { handle.button(data, event); if handle.current_pressed().is_empty() { @@ -121,7 +104,7 @@ impl> PointerGrab for DelayGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { handle.axis(data, details); } @@ -218,17 +201,12 @@ impl> TouchGrab for DelayGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(::TouchFocus, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { handle.down(data, focus, event); } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { handle.up(data, event); if event.slot == TouchGrab::start_data(self).slot { @@ -295,110 +273,3 @@ 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 26cca2f5..c7418b6d 100644 --- a/src/shell/grabs/menu/default.rs +++ b/src/shell/grabs/menu/default.rs @@ -1,10 +1,7 @@ use cosmic_settings_config::shortcuts::Action; use smithay::{ - backend::input::InputTime, - input::{pointer::MotionEvent, tablet::TabletSeatTrait}, - reexports::wayland_server::protocol::wl_surface::WlSurface, - utils::SERIAL_COUNTER, - wayland::seat::WaylandFocus, + input::pointer::MotionEvent, reexports::wayland_server::protocol::wl_surface::WlSurface, + utils::SERIAL_COUNTER, wayland::seat::WaylandFocus, }; use crate::{ @@ -13,7 +10,7 @@ use crate::{ shell::{ CosmicSurface, PointGlobalExt, Shell, element::{CosmicMapped, CosmicWindow}, - grabs::{GrabType, ReleaseMode}, + grabs::ReleaseMode, }, state::State, utils::{prelude::SeatExt, screenshot::screenshot_window}, @@ -355,20 +352,19 @@ pub fn window_items( std::mem::drop(shell); if let Some((grab, focus)) = res { - 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), + 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, + ); } } } @@ -392,29 +388,21 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - 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); - } + 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); } } }); @@ -435,30 +423,21 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - 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); - } + 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); } } }); @@ -479,30 +458,21 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - 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); - } + 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); } } }); @@ -523,29 +493,21 @@ pub fn window_items( std::mem::drop(shell); if let Some(((target, loc), (grab, focus))) = res { let serial = SERIAL_COUNTER.next_serial(); - 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), + 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); } } }); @@ -665,20 +627,19 @@ pub fn fullscreen_items(window: &CosmicSurface, config: &Config) -> impl Iterato std::mem::drop(shell); if let Some((grab, focus)) = res { - 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), + 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, + ); } } } diff --git a/src/shell/grabs/menu/mod.rs b/src/shell/grabs/menu/mod.rs index 9ea37a31..1eb571f1 100644 --- a/src/shell/grabs/menu/mod.rs +++ b/src/shell/grabs/menu/mod.rs @@ -19,33 +19,22 @@ use cosmic::{ }; use smithay::{ backend::{ - input::{ButtonState, InputTime, TabletToolDescriptor, TouchSlot}, + input::{ButtonState, TouchSlot}, renderer::ImportMem, }, desktop::space::SpaceElement, input::{ Seat, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent as PointerMotionEvent, PointerGrab, + PointerInnerHandle, PointerTarget, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, - MotionEvent as TouchMotionEvent, TouchGrab, TouchInnerHandle, TouchTarget, - UpEvent as TouchUpEvent, + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + TouchGrab, TouchInnerHandle, TouchTarget, UpEvent, }, }, output::Output, @@ -54,7 +43,7 @@ use smithay::{ use crate::{ backend::render::element::AsGlowRenderer, - shell::{SeatExt, focus::target::PointerFocusTarget, grabs::GrabType}, + shell::{SeatExt, focus::target::PointerFocusTarget}, state::State, utils::{ iced::{IcedElement, IcedRenderElement, Program}, @@ -361,7 +350,6 @@ impl Program for ContextMenu { position, pointer_entered: false, touch_entered: None, - tablet_entered: None, }) } }); @@ -521,7 +509,6 @@ pub struct Element { position: Point, pointer_entered: bool, touch_entered: Option, - tablet_entered: Option, } pub struct MenuGrab { @@ -530,7 +517,6 @@ pub struct MenuGrab { seat: Seat, screen_space_relative: Option, scale: Arc>, - last_tablet_idx: Option, } impl PointerGrab for MenuGrab { @@ -613,7 +599,7 @@ impl PointerGrab for MenuGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { let any_entered = self .elements @@ -647,7 +633,7 @@ impl PointerGrab for MenuGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { handle.axis(state, details); } @@ -744,7 +730,7 @@ impl TouchGrab for MenuGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { { let mut guard = self.elements.lock().unwrap(); @@ -772,7 +758,7 @@ impl TouchGrab for MenuGrab { }) { let element = &mut elements[i]; - let new_event = TouchDownEvent { + let new_event = DownEvent { slot: event.slot, location: event_location - element.position.as_logical().to_f64(), serial: event.serial, @@ -787,12 +773,7 @@ impl TouchGrab for MenuGrab { handle.down(data, None, event); } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { { let elements = self.elements.lock().unwrap(); for element in elements.iter().filter(|elem| { @@ -868,248 +849,6 @@ 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, @@ -1313,7 +1052,6 @@ impl MenuGrab { position, pointer_entered: false, touch_entered: None, - tablet_entered: None, }])); let scale = Arc::new(Mutex::new(screen_space_relative.unwrap_or(1.))); @@ -1338,7 +1076,6 @@ impl MenuGrab { seat: seat.clone(), screen_space_relative, scale, - last_tablet_idx: None, } } @@ -1349,15 +1086,10 @@ impl MenuGrab { } } - 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 + pub fn is_touch_grab(&self) -> bool { + match self.start_data { + GrabStartData::Touch(_) => true, + GrabStartData::Pointer(_) => false, } } } diff --git a/src/shell/grabs/mod.rs b/src/shell/grabs/mod.rs index 9524f425..515916fd 100644 --- a/src/shell/grabs/mod.rs +++ b/src/shell/grabs/mod.rs @@ -1,26 +1,18 @@ use calloop::LoopHandle; use cosmic_settings_config::shortcuts; use smithay::{ - backend::input::{InputTime, TabletToolDescriptor}, input::{ Seat, pointer::{ - 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, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, GrabStartData as TouchGrabStartData, - MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, UpEvent as TouchUpEvent, + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, }, }, output::Output, @@ -47,17 +39,6 @@ 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 { @@ -65,7 +46,6 @@ 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(), } } @@ -73,7 +53,6 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.focus = focus, Self::Pointer(pointer) => pointer.focus = focus, - Self::TabletTool { data, .. } => data.focus = focus, } } @@ -81,7 +60,6 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.location, Self::Pointer(pointer) => pointer.location, - Self::TabletTool { data, .. } => data.location, } } @@ -89,7 +67,6 @@ impl GrabStartData { match self { Self::Touch(touch) => touch.location = location, Self::Pointer(pointer) => pointer.location = location, - Self::TabletTool { data, .. } => data.location = location, } } @@ -99,14 +76,6 @@ 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)] @@ -234,17 +203,10 @@ impl From for ResizeGrab { } impl ResizeGrab { - pub fn grab_type(&self) -> GrabType { + pub fn is_touch_grab(&self) -> bool { match self { - 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(), + ResizeGrab::Floating(grab) => grab.is_touch_grab(), + ResizeGrab::Tiling(grab) => grab.is_touch_grab(), } } } @@ -280,11 +242,11 @@ impl PointerGrab for ResizeGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { match self { - ResizeGrab::Floating(grab) => PointerGrab::button(grab, data, handle, event), - ResizeGrab::Tiling(grab) => PointerGrab::button(grab, data, handle, event), + ResizeGrab::Floating(grab) => grab.button(data, handle, event), + ResizeGrab::Tiling(grab) => grab.button(data, handle, event), } } @@ -292,11 +254,11 @@ impl PointerGrab for ResizeGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { match self { - ResizeGrab::Floating(grab) => PointerGrab::axis(grab, data, handle, details), - ResizeGrab::Tiling(grab) => PointerGrab::axis(grab, data, handle, details), + ResizeGrab::Floating(grab) => grab.axis(data, handle, details), + ResizeGrab::Tiling(grab) => grab.axis(data, handle, details), } } @@ -424,7 +386,7 @@ impl TouchGrab for ResizeGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { match self { ResizeGrab::Floating(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -432,12 +394,7 @@ impl TouchGrab for ResizeGrab { } } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { match self { ResizeGrab::Floating(grab) => TouchGrab::up(grab, data, handle, event), ResizeGrab::Tiling(grab) => TouchGrab::up(grab, data, handle, event), @@ -510,107 +467,6 @@ 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), @@ -680,17 +536,10 @@ impl MoveGrab { } } - pub fn grab_type(&self) -> GrabType { + pub fn is_touch_grab(&self) -> bool { match self { - 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(), + MoveGrab::Move(m) => m.is_touch_grab(), + MoveGrab::Delayed(d) => d.is_touch_grab(), } } } @@ -725,11 +574,11 @@ impl PointerGrab for MoveGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { match self { - MoveGrab::Move(grab) => PointerGrab::button(grab, data, handle, event), - MoveGrab::Delayed(grab) => PointerGrab::button(grab, data, handle, event), + MoveGrab::Move(grab) => grab.button(data, handle, event), + MoveGrab::Delayed(grab) => grab.button(data, handle, event), } } @@ -737,11 +586,11 @@ impl PointerGrab for MoveGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { match self { - MoveGrab::Move(grab) => PointerGrab::axis(grab, data, handle, details), - MoveGrab::Delayed(grab) => PointerGrab::axis(grab, data, handle, details), + MoveGrab::Move(grab) => grab.axis(data, handle, details), + MoveGrab::Delayed(grab) => grab.axis(data, handle, details), } } @@ -869,7 +718,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { match self { MoveGrab::Move(grab) => TouchGrab::down(grab, data, handle, focus, event), @@ -877,12 +726,7 @@ impl TouchGrab for MoveGrab { } } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { match self { MoveGrab::Move(grab) => TouchGrab::up(grab, data, handle, event), MoveGrab::Delayed(grab) => TouchGrab::up(grab, data, handle, event), @@ -954,104 +798,3 @@ 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 f1fbfa8a..d8714830 100644 --- a/src/shell/grabs/moving.rs +++ b/src/shell/grabs/moving.rs @@ -8,7 +8,6 @@ use crate::{ CosmicMapped, CosmicSurface, Direction, ManagedLayer, element::{CosmicMappedRenderElement, stack_hover::StackHover}, focus::target::{KeyboardFocusTarget, PointerFocusTarget}, - grabs::GrabType, layout::floating::TiledCorners, }, utils::prelude::*, @@ -21,7 +20,7 @@ use smallvec::SmallVec; use smithay::{ backend::{ drm::DrmNode, - input::{ButtonState, InputTime, TabletToolDescriptor}, + input::ButtonState, renderer::{ ImportAll, ImportMem, element::{RenderElement, utils::RescaleRenderElement}, @@ -31,27 +30,13 @@ use smithay::{ input::{ Seat, pointer::{ - AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, - GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, - GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, - GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, - MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, + AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, 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 as TouchDownEvent, GrabStartData as TouchGrabStartData, - MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, UpEvent as TouchUpEvent, - }, + touch::{self, GrabStartData as TouchGrabStartData, TouchGrab, TouchInnerHandle}, }, output::Output, utils::{IsAlive, Logical, Point, Rectangle, SERIAL_COUNTER, Scale}, @@ -518,7 +503,7 @@ impl PointerGrab for MoveGrab { state: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &PointerMotionEvent, + event: &MotionEvent, ) { self.update_location(state, event.location); @@ -544,7 +529,7 @@ impl PointerGrab for MoveGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { handle.button(state, event); match self.release { @@ -565,7 +550,7 @@ impl PointerGrab for MoveGrab { &mut self, state: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { handle.axis(state, details); } @@ -662,7 +647,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &touch::DownEvent, ) { handle.down(data, None, event) } @@ -671,7 +656,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, + event: &touch::UpEvent, ) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); @@ -685,7 +670,7 @@ impl TouchGrab for MoveGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &TouchMotionEvent, + event: &touch::MotionEvent, ) { if event.slot == >::start_data(self).slot { self.update_location(data, event.location); @@ -706,7 +691,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &ShapeEvent, + event: &touch::ShapeEvent, ) { handle.shape(data, event) } @@ -715,7 +700,7 @@ impl TouchGrab for MoveGrab { &mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, - event: &OrientationEvent, + event: &touch::OrientationEvent, ) { handle.orientation(data, event) } @@ -730,98 +715,6 @@ 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, @@ -885,15 +778,10 @@ impl MoveGrab { self.previous == ManagedLayer::Tiling } - 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 + pub fn is_touch_grab(&self) -> bool { + match self.start_data { + GrabStartData::Touch(_) => true, + GrabStartData::Pointer(_) => false, } } } @@ -905,7 +793,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 = std::mem::take(&mut self.window_outputs); + let window_outputs = self.window_outputs.drain().collect::>(); let previous = self.previous; let window = self.window.clone(); let is_touch_grab = matches!(self.start_data, GrabStartData::Touch(_)); @@ -1065,10 +953,10 @@ impl Drop for MoveGrab { position.as_logical().to_f64() - window.geometry().loc.to_f64() + offset, )), - &PointerMotionEvent { + &MotionEvent { location: pointer.current_location(), serial, - time: InputTime::now(), + time: state.common.clock.now().as_millis(), }, ); } diff --git a/src/shell/layout/floating/grabs/resize.rs b/src/shell/layout/floating/grabs/resize.rs index 9d767671..f9e5cbfd 100644 --- a/src/shell/layout/floating/grabs/resize.rs +++ b/src/shell/layout/floating/grabs/resize.rs @@ -7,36 +7,25 @@ use crate::{ shell::{ element::CosmicMapped, focus::target::PointerFocusTarget, - grabs::{GrabStartData, GrabType, ReleaseMode, ResizeEdge}, + grabs::{GrabStartData, ReleaseMode, ResizeEdge}, }, utils::prelude::*, }; use smithay::{ - backend::input::{ButtonState, InputTime, TabletToolDescriptor}, + backend::input::ButtonState, desktop::{WindowSurface, space::SpaceElement}, input::{ Seat, pointer::{ - AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, CursorIcon, - GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, - GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, - GestureSwipeEndEvent, GestureSwipeUpdateEvent, GrabStartData as PointerGrabStartData, - MotionEvent as PointerMotionEvent, PointerGrab, PointerInnerHandle, + AxisFrame, ButtonEvent, CursorIcon, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, 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 as TouchDownEvent, GrabStartData as TouchGrabStartData, - MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, UpEvent as TouchUpEvent, + DownEvent, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, + OrientationEvent, ShapeEvent, TouchGrab, TouchInnerHandle, UpEvent, }, }, output::Output, @@ -181,19 +170,10 @@ impl ResizeSurfaceGrab { false } - pub fn grab_type(&self) -> GrabType { + pub fn is_touch_grab(&self) -> bool { match self.start_data { - 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 + GrabStartData::Touch(_) => true, + GrabStartData::Pointer(_) => false, } } } @@ -204,7 +184,7 @@ impl PointerGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &PointerMotionEvent, + event: &MotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -229,7 +209,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { handle.button(data, event); match self.release { @@ -250,7 +230,7 @@ impl PointerGrab for ResizeSurfaceGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { handle.axis(data, details) } @@ -349,17 +329,12 @@ impl TouchGrab for ResizeSurfaceGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { handle.down(data, None, event) } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -421,99 +396,6 @@ 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 c6f202cf..9b135119 100644 --- a/src/shell/layout/tiling/grabs/resize.rs +++ b/src/shell/layout/tiling/grabs/resize.rs @@ -4,42 +4,31 @@ use crate::{ backend::render::cursor::CursorState, shell::{ focus::target::PointerFocusTarget, - grabs::{GrabStartData, GrabType, ReleaseMode}, + grabs::{GrabStartData, ReleaseMode}, layout::Orientation, }, utils::prelude::*, }; use id_tree::{NodeId, Tree}; use smithay::{ - backend::input::{ButtonState, InputTime, TabletToolDescriptor}, + backend::input::ButtonState, input::{ Seat, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, CursorIcon, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + GrabStartData as PointerGrabStartData, MotionEvent, PointerGrab, PointerInnerHandle, + PointerTarget, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, GrabStartData as TouchGrabStartData, + DownEvent, FrameMarker, GrabStartData as TouchGrabStartData, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, TouchGrab, - TouchInnerHandle, TouchTarget, UpEvent as TouchUpEvent, + TouchInnerHandle, TouchTarget, UpEvent, }, }, output::WeakOutput, - utils::{IsAlive, Logical, Point, Serial}, + utils::{IsAlive, Logical, Point}, }; use super::super::{Data, TilingLayout}; @@ -59,7 +48,7 @@ impl IsAlive for ResizeForkTarget { } impl PointerTarget for ResizeForkTarget { - fn enter(&self, seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) { + fn enter(&self, seat: &Seat, _data: &mut State, _event: &MotionEvent) { let user_data = seat.user_data(); let cursor_state = user_data.get::().unwrap(); cursor_state @@ -71,13 +60,19 @@ impl PointerTarget for ResizeForkTarget { }); } - fn leave(&self, seat: &Seat, _data: &mut State, _serial: Serial, _time: InputTime) { + fn leave( + &self, + seat: &Seat, + _data: &mut State, + _serial: smithay::utils::Serial, + _time: u32, + ) { 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: &PointerButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { if event.button == 0x110 && event.state == ButtonState::Pressed { let seat = seat.clone(); let node = self.node.clone(); @@ -111,7 +106,7 @@ impl PointerTarget for ResizeForkTarget { } } - fn motion(&self, _seat: &Seat, _data: &mut State, _event: &PointerMotionEvent) {} + fn motion(&self, _seat: &Seat, _data: &mut State, _event: &MotionEvent) {} fn relative_motion( &self, _seat: &Seat, @@ -119,7 +114,7 @@ impl PointerTarget for ResizeForkTarget { _event: &RelativeMotionEvent, ) { } - fn axis(&self, _seat: &Seat, _data: &mut State, _frame: PointerAxisFrame) {} + fn axis(&self, _seat: &Seat, _data: &mut State, _frame: AxisFrame) {} 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) {} @@ -132,7 +127,7 @@ impl PointerTarget for ResizeForkTarget { } impl TouchTarget for ResizeForkTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { let seat = seat.clone(); let node = self.node.clone(); let output = self.output.clone(); @@ -163,7 +158,7 @@ impl TouchTarget for ResizeForkTarget { }); } - fn up(&self, _seat: &Seat, _data: &mut State, _event: &TouchUpEvent) {} + fn up(&self, _seat: &Seat, _data: &mut State, _event: &UpEvent) {} 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) {} @@ -174,121 +169,6 @@ 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, @@ -458,19 +338,10 @@ impl ResizeForkGrab { false } - pub fn grab_type(&self) -> GrabType { + pub fn is_touch_grab(&self) -> bool { match self.start_data { - 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 + GrabStartData::Touch(_) => true, + GrabStartData::Pointer(_) => false, } } } @@ -481,7 +352,7 @@ impl PointerGrab for ResizeForkGrab { data: &mut State, handle: &mut PointerInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &PointerMotionEvent, + event: &MotionEvent, ) { // While the grab is active, no client has pointer focus handle.motion(data, None, event); @@ -506,7 +377,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { handle.button(data, event); match self.release { @@ -527,7 +398,7 @@ impl PointerGrab for ResizeForkGrab { &mut self, data: &mut State, handle: &mut PointerInnerHandle<'_, State>, - details: PointerAxisFrame, + details: AxisFrame, ) { handle.axis(data, details) } @@ -626,17 +497,12 @@ impl TouchGrab for ResizeForkGrab { data: &mut State, handle: &mut TouchInnerHandle<'_, State>, _focus: Option<(PointerFocusTarget, Point)>, - event: &TouchDownEvent, + event: &DownEvent, ) { handle.down(data, None, event) } - fn up( - &mut self, - data: &mut State, - handle: &mut TouchInnerHandle<'_, State>, - event: &TouchUpEvent, - ) { + fn up(&mut self, data: &mut State, handle: &mut TouchInnerHandle<'_, State>, event: &UpEvent) { if event.slot == >::start_data(self).slot { handle.unset_grab(self, data); } @@ -697,96 +563,3 @@ 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 9ac531d3..4c22209f 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::{InputTime, KeyState, Keycode}, + backend::input::{KeyState, Keycode}, input::{ Seat, SeatHandler, keyboard::{ @@ -13,7 +13,6 @@ use smithay::{ use crate::{ config::key_bindings::cosmic_modifiers_from_smithay, - input::InputBackendId, shell::{Trigger, layout::tiling::NodeDesc}, state::State, }; @@ -38,7 +37,7 @@ impl KeyboardGrab for SwapWindowGrab { state: KeyState, modifiers: Option, serial: Serial, - time: InputTime, + time: u32, ) { if !matches!(&data.common.shell.read().overview_mode.active_trigger(), Some(Trigger::KeyboardSwap(_, d)) if d == &self.desc) { @@ -74,7 +73,6 @@ impl KeyboardGrab for SwapWindowGrab { data.handle_shortcut_action( shortcuts::Action::Focus(direction), - &InputBackendId::Normal, &self.seat, serial, time, diff --git a/src/shell/layout/tiling/mod.rs b/src/shell/layout/tiling/mod.rs index 8706dc59..2d95cd27 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(_) | Trigger::Tool(_, _)) + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) && 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(_) | Trigger::Tool(_, _)) + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { let non_exclusive_zone = layer_map_for_output(&self.output) .non_exclusive_zone() @@ -4062,11 +4062,8 @@ 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(_) | Trigger::Tool(_, _)) - )) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) + .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 { @@ -4219,11 +4216,8 @@ impl TilingLayout { }; let draw_groups = overview.0.alpha(); - let is_mouse_tiling = (matches!( - overview.0.trigger(), - Some(Trigger::Pointer(_) | Trigger::Tool(_, _)) - )) - .then(|| self.last_overview_hover.as_ref().map(|(_, zone)| zone)); + let is_mouse_tiling = (matches!(overview.0.trigger(), Some(Trigger::Pointer(_)))) + .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 8439b13f..39d692e2 100644 --- a/src/shell/mod.rs +++ b/src/shell/mod.rs @@ -19,10 +19,7 @@ use crate::{ utils, wayland::{ handlers::data_device::{self, get_dnd_icon}, - protocols::{ - session_lock_layer::layer_show_on_lock, - workspace::{State as WState, WorkspaceCapabilities}, - }, + protocols::workspace::{State as WState, WorkspaceCapabilities}, }, }; use cosmic_comp_config::{ @@ -35,10 +32,7 @@ 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::{TabletToolDescriptor, TouchSlot}, - renderer::element::RenderElementStates, - }, + backend::{input::TouchSlot, renderer::element::RenderElementStates}, desktop::{ LayerSurface, PopupKind, WindowSurface, WindowSurfaceType, layer_map_for_output, space::SpaceElement, @@ -52,7 +46,6 @@ use smithay::{ pointer::{ CursorImageStatus, CursorImageSurfaceData, Focus, GrabStartData as PointerGrabStartData, }, - tablet::{TabletSeatTrait, tool::GrabTrigger as TabletGrabTrigger}, }, output::{Output, WeakOutput}, reexports::{ @@ -137,7 +130,6 @@ pub enum Trigger { KeyboardMove(shortcuts::Modifiers), Pointer(u32), Touch(TouchSlot), - Tool(TabletToolDescriptor, TabletGrabTrigger), } #[derive(Debug, Clone)] @@ -262,7 +254,6 @@ pub struct PendingWindow { pub surface: CosmicSurface, pub seat: Seat, pub fullscreen: Option, - pub minimized: bool, pub maximized: bool, pub sticky: bool, } @@ -1623,29 +1614,6 @@ impl Common { a11y_keyboard_monitor.refresh(); } self.image_copy_capture_state.cleanup(); - self.cleanup_cursor_images(); - } - - /// Release the enlarged cursor frames a finished shake or zoom left behind. - fn cleanup_cursor_images(&mut self) { - let shell = self.shell.read(); - let zoomed = shell.zoom_state.as_ref().is_some_and(|zoom_state| { - shell - .outputs() - .any(|output| zoom_state.animating_level(output) > 1.0) - }); - let now = Instant::now(); - for seat in shell.seats.iter() { - if let Some(cursor_state) = seat - .user_data() - .get::() - { - cursor_state - .lock() - .unwrap() - .drop_magnified_frames(now, zoomed); - } - } } pub fn refresh_idle_inhibit(&mut self) { @@ -1763,7 +1731,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(_) | Trigger::Tool(_, _)) + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -1814,7 +1782,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(_) | Trigger::Tool(_, _)) + Some(Trigger::Pointer(_) | Trigger::Touch(_)) ) { set.workspaces[set.active].tiling_layer.cleanup_drag(); } @@ -2049,27 +2017,12 @@ impl Shell { } pub fn visible_output_for_surface(&self, surface: &WlSurface) -> Option<&Output> { - // NOTE: Keep in sync with surface iteration in `render_input_order_internal` - if let Some(session_lock) = &self.session_lock { - if let Some((output, _)) = session_lock + return session_lock .surfaces .iter() .find(|(_, v)| v.wl_surface() == surface) - { - return Some(output); - } - for o in self.outputs() { - let map = layer_map_for_output(o); - if let Some(layer_surface) = map.layer_for_surface(surface, WindowSurfaceType::ALL) - { - if layer_show_on_lock(layer_surface.wl_surface()) { - return Some(o); - } else { - return None; - } - } - } + .map(|(k, _)| k); } self.outputs() @@ -2333,11 +2286,6 @@ impl Shell { .is_some_and(|state| state.lock().unwrap().is_animating()) }) }) - || self.seats.iter().any(|seat| { - seat.user_data() - .get::() - .is_some_and(|state| state.lock().unwrap().is_magnifying()) - }) } pub fn update_animations(&mut self) -> HashMap { @@ -2880,7 +2828,6 @@ 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); @@ -2964,7 +2911,6 @@ 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) { @@ -3014,13 +2960,8 @@ impl Shell { self.maximize_request(&mapped, &seat, false, loop_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) + let new_target = 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. @@ -3144,7 +3085,6 @@ impl Shell { surface, seat: seat.clone(), fullscreen: None, - minimized: false, maximized: false, sticky: false, }); @@ -3863,7 +3803,6 @@ 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 @@ -5085,20 +5024,6 @@ impl Shell { let mut output_presentation_feedback = OutputPresentationFeedback::new(output); if let Some(active) = self.active_space(output) { - for fs in active.get_fullscreen_surfaces() { - fs.surface.take_presentation_feedback( - &mut output_presentation_feedback, - surface_primary_scanout_output, - |surface, _| { - surface_presentation_feedback_flags_from_states( - surface, - None, - render_element_states, - ) - }, - ); - } - active.mapped().for_each(|mapped| { mapped.active_window().take_presentation_feedback( &mut output_presentation_feedback, @@ -5182,19 +5107,10 @@ 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 { @@ -5208,16 +5124,8 @@ 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) - || tools.values().any(|tool| tool.has_grab(serial)) - } - None => { - pointer.is_grabbed() - || touch.is_grabbed() - || tools.values().any(|tool| tool.is_grabbed()) - } + Some(serial) => pointer.has_grab(serial) || touch.has_grab(serial), + None => pointer.is_grabbed() | touch.is_grabbed(), } { return None; } diff --git a/src/shell/seats.rs b/src/shell/seats.rs index 27b608cf..11211e90 100644 --- a/src/shell/seats.rs +++ b/src/shell/seats.rs @@ -5,7 +5,7 @@ use std::{any::Any, cell::RefCell, collections::HashMap, sync::Mutex}; use crate::{ backend::render::cursor::CursorState, config::{Config, xkb_config_to_wl}, - input::{InputBackendId, ModifiersShortcutQueue, SupressedButtons, SupressedKeys}, + input::{ModifiersShortcutQueue, SupressedButtons, SupressedKeys}, state::State, }; use smithay::{ @@ -82,25 +82,12 @@ impl Seats { self.last_active = Some(seat.clone()); } - pub fn for_device( - &self, - device: &D, - backend_id: &InputBackendId, - ) -> Option<&Seat> { - self.iter() - .find(|seat| { - let userdata = seat.user_data(); - let devices = userdata.get::().unwrap(); - devices.has_device(device, backend_id) - }) - .or_else(|| { - // EI devices can be transiently unregistered while the compositor recreates - // the absolute-pointer device (e.g. on a scale/geometry change), which would - // otherwise drop all pointer/touch input until the client re-binds it. EI is - // single-seat, so fall back to the active seat here, matching the EI keyboard - // path, which always targets the active seat. - matches!(backend_id, InputBackendId::Ei(_)).then(|| self.last_active()) - }) + pub fn for_device(&self, device: &D) -> Option<&Seat> { + self.iter().find(|seat| { + let userdata = seat.user_data(); + let devices = userdata.get::().unwrap(); + devices.has_device(device) + }) } } @@ -109,7 +96,6 @@ impl Devices { &self, device: &D, led_state: LedState, - backend_id: &InputBackendId, ) -> Vec { let id = device.id(); let mut map = self.capabilities.borrow_mut(); @@ -127,7 +113,7 @@ impl Devices { .cloned() .filter(|c| map.values().flatten().all(|has| *c != *has)) .collect::>(); - map.insert((backend_id.clone(), id), caps); + map.insert(id, caps); if device.has_capability(DeviceCapability::Keyboard) && let Some(device) = ::downcast_ref::(device) @@ -140,18 +126,11 @@ impl Devices { new_caps } - /// Whether the given backend's device with this id is registered on the seat. - pub fn has_device(&self, device: &D, backend_id: &InputBackendId) -> bool { - self.capabilities - .borrow() - .contains_key(&(backend_id.clone(), device.id())) + pub fn has_device(&self, device: &D) -> bool { + self.capabilities.borrow().contains_key(&device.id()) } - pub fn remove_device( - &self, - device: &D, - backend_id: &InputBackendId, - ) -> Vec { + pub fn remove_device(&self, device: &D) -> Vec { let id = device.id(); let mut keyboards = self.keyboards.borrow_mut(); @@ -160,7 +139,7 @@ impl Devices { } let mut map = self.capabilities.borrow_mut(); - map.remove(&(backend_id.clone(), id)) + map.remove(&id) .unwrap_or_default() .into_iter() .filter(|c| map.values().flatten().all(|has| *c != *has)) @@ -176,8 +155,7 @@ impl Devices { #[derive(Default)] pub struct Devices { - // Keyed by `(backend, device_id)` - capabilities: RefCell>>, + capabilities: RefCell>>, // Used for updating keyboard leds on kms backend keyboards: RefCell>, } @@ -207,7 +185,7 @@ struct FocusedOutput(pub Mutex>); pub struct PointerConstraintHint(pub Mutex)>>); #[derive(Default)] -pub struct LastModifierChange(pub Mutex<(HashMap, Option)>); +pub struct LastModifierChange(pub Mutex>); pub fn create_seat( dh: &DisplayHandle, @@ -287,9 +265,6 @@ pub trait SeatExt { fn supressed_buttons(&self) -> &SupressedButtons; fn modifiers_shortcut_queue(&self) -> &ModifiersShortcutQueue; fn last_modifier_change(&self) -> Option; - fn last_modifier_change_for(&self, backend_id: &InputBackendId) -> Option; - fn set_last_modifier_change(&self, backend_id: &InputBackendId, serial: Serial); - fn clear_last_modifier_change(&self, backend_id: &InputBackendId); fn pointer_constraint_hint(&self) -> Option<(WlSurface, Point)>; fn set_pointer_constraint_hint(&self, hint: Option<(WlSurface, Point)>); @@ -368,48 +343,13 @@ impl SeatExt for Seat { } fn last_modifier_change(&self) -> Option { - self.user_data() - .get::() - .unwrap() - .0 - .lock() - .unwrap() - .1 - } - - fn last_modifier_change_for(&self, backend_id: &InputBackendId) -> Option { - self.user_data() - .get::() - .unwrap() - .0 - .lock() - .unwrap() - .0 - .get(backend_id) - .copied() - } - - fn set_last_modifier_change(&self, backend_id: &InputBackendId, serial: Serial) { - let mut guard = self + *self .user_data() .get::() .unwrap() .0 .lock() - .unwrap(); - guard.0.insert(backend_id.clone(), serial); - guard.1 = Some(serial); - } - - fn clear_last_modifier_change(&self, backend_id: &InputBackendId) { - self.user_data() - .get::() .unwrap() - .0 - .lock() - .unwrap() - .0 - .remove(backend_id); } fn pointer_constraint_hint(&self) -> Option<(WlSurface, Point)> { diff --git a/src/shell/zoom.rs b/src/shell/zoom.rs index dcddfb27..8363510a 100644 --- a/src/shell/zoom.rs +++ b/src/shell/zoom.rs @@ -7,35 +7,23 @@ use cosmic::{ theme, widget::{self, icon::Named}, }; -use cosmic_comp_config::{ZoomConfig, ZoomMovement}; +use cosmic_comp_config::ZoomMovement; use cosmic_config::ConfigSet; use keyframe::{ease, functions::Linear}; use smithay::{ - backend::{ - input::{InputTime, TabletToolDescriptor}, - renderer::ImportMem, - }, + backend::renderer::ImportMem, desktop::space::SpaceElement, input::{ Seat, pointer::{ - 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, - }, + AxisFrame, ButtonEvent, Focus, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, + MotionEvent as PointerMotionEvent, PointerTarget, RelativeMotionEvent, }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, + DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, + TouchTarget, UpEvent, }, }, output::Output, @@ -45,7 +33,6 @@ use tracing::error; use crate::{ backend::render::element::AsGlowRenderer, - shell::grabs::GrabType, state::State, utils::{ iced::{IcedElement, IcedRenderElement, Program}, @@ -460,7 +447,7 @@ pub enum MenuMessage { impl ZoomProgram { pub fn new(level: f64, movement: ZoomMovement, increment: u32) -> Self { - let mut increments = ZoomConfig::ZOOM_INCREMENT_PRESETS.to_vec(); + let mut increments = vec![25, 50, 100, 150, 200]; if !increments.contains(&increment) { increments.push(increment); } @@ -712,27 +699,15 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - match grab.grab_type() { - GrabType::Touch => { - seat.get_touch().unwrap().set_grab(state, grab, serial) - } - GrabType::Pointer => seat.get_pointer().unwrap().set_grab( + 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::Clear, - ), - GrabType::TabletTool => seat - .tablet_seat() - .get_tool(grab.tool().unwrap()) - .unwrap() - .set_grab( - state, - grab, - InputTime::now(), - serial, - Focus::Clear, - ), + ); } } } @@ -811,27 +786,15 @@ impl Program for ZoomProgram { ); std::mem::drop(shell); - match grab.grab_type() { - GrabType::Touch => { - seat.get_touch().unwrap().set_grab(state, grab, serial) - } - GrabType::Pointer => seat.get_pointer().unwrap().set_grab( + 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::Clear, - ), - GrabType::TabletTool => seat - .tablet_seat() - .get_tool(grab.tool().unwrap()) - .unwrap() - .set_grab( - state, - grab, - InputTime::now(), - serial, - Focus::Clear, - ), + ); } } } @@ -866,7 +829,7 @@ impl Program for ZoomProgram { if let Some(pos) = self.increments.iter().position(|val| *val == increment) { self.increment_idx = pos; } else { - let mut increments = ZoomConfig::ZOOM_INCREMENT_PRESETS.to_vec(); + let mut increments = vec![25, 50, 100, 150, 200]; if !increments.contains(&increment) { increments.push(increment); } @@ -921,14 +884,14 @@ impl PointerTarget for ZoomFocusTarget { } } - fn button(&self, seat: &Seat, data: &mut State, event: &PointerButtonEvent) { + fn button(&self, seat: &Seat, data: &mut State, event: &ButtonEvent) { 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: PointerAxisFrame) { + fn axis(&self, seat: &Seat, data: &mut State, frame: AxisFrame) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::axis(elem, seat, data, frame), ZoomFocusTarget::Menu(elem) => PointerTarget::axis(elem, seat, data, frame), @@ -1061,7 +1024,7 @@ impl PointerTarget for ZoomFocusTarget { } } - fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: InputTime) { + fn leave(&self, seat: &Seat, data: &mut State, serial: Serial, time: u32) { match self { ZoomFocusTarget::Main(elem) => PointerTarget::leave(elem, seat, data, serial, time), ZoomFocusTarget::Menu(elem) => PointerTarget::leave(elem, seat, data, serial, time), @@ -1070,14 +1033,14 @@ impl PointerTarget for ZoomFocusTarget { } impl TouchTarget for ZoomFocusTarget { - fn down(&self, seat: &Seat, data: &mut State, event: &TouchDownEvent) { + fn down(&self, seat: &Seat, data: &mut State, event: &DownEvent) { 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: &TouchUpEvent) { + fn up(&self, seat: &Seat, data: &mut State, event: &UpEvent) { match self { ZoomFocusTarget::Main(elem) => TouchTarget::up(elem, seat, data, event), ZoomFocusTarget::Menu(elem) => TouchTarget::up(elem, seat, data, event), @@ -1127,144 +1090,6 @@ 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 86f5e23e..21cbb400 100644 --- a/src/state.rs +++ b/src/state.rs @@ -23,7 +23,6 @@ use crate::{ output_configuration::OutputConfigurationState, output_power::OutputPowerState, overlap_notify::OverlapNotifyState, - session_lock_layer::SessionLockLayerState, toplevel_info::ToplevelInfoState, toplevel_management::{ManagementCapabilities, ToplevelManagementState}, workspace::{WorkspaceState, WorkspaceUpdateGuard}, @@ -245,32 +244,9 @@ pub struct Common { pub clock: Clock, pub startup_done: Arc, pub should_stop: bool, - pub kiosk_exit_code: Option, pub gesture_state: Option, - /// Active libei sender seats, keyed by their `eis` connection. Tracked so their virtual - /// keyboards can be re-created when the keyboard configuration changes at runtime. - pub ei_seats: std::collections::HashMap< - smithay::reexports::reis::eis::Connection, - smithay::backend::libei::EiInputSeat, - >, - - /// The shared-seat [`KeyboardSource`] assigned to each libei connection, so its - /// `ei_keyboard` key events feed the seat keyboard with independent per-source hold - /// tracking (and can be released together on disconnect). Keyed by connection. - pub ei_keyboard_source: std::collections::HashMap< - smithay::reexports::reis::eis::Connection, - smithay::input::keyboard::KeyboardSource, - >, - - /// Pointer buttons currently held by each libei connection, so they can be released when the - /// connection drops - pub ei_pointer_buttons: std::collections::HashMap< - smithay::reexports::reis::eis::Connection, - std::collections::HashSet, - >, - pub kiosk_child: Option, pub theme: cosmic::Theme, @@ -299,7 +275,7 @@ pub struct Common { pub idle_inhibiting_surfaces: HashSet, pub shm_state: ShmState, pub cursor_shape_manager_state: CursorShapeManagerState, - pub wl_drm_state: Option>>, + pub wl_drm_state: WlDrmState>, pub viewporter_state: ViewporterState, pub kde_decoration_state: KdeDecorationState, pub xdg_decoration_state: XdgDecorationState, @@ -321,7 +297,6 @@ pub struct Common { pub xwayland_state: Option, pub xwayland_shell_state: XWaylandShellState, pub pointer_focus_state: Option, - pub session_lock_layer_state: SessionLockLayerState, #[cfg(feature = "logind")] pub inhibit_lid_fd: Option, @@ -350,7 +325,7 @@ pub enum LockedBackend<'a> { pub struct SurfaceDmabufFeedback { pub render_feedback: DmabufFeedback, pub overlay_scanout_feedback: Option, - pub primary_scanout_feedback: DmabufFeedback, + pub primary_scanout_feedback: Option, } #[derive(Debug)] @@ -667,7 +642,7 @@ impl State { .unwrap(); let clock = Clock::new(); - let config = Config::load(&handle, kiosk_command.is_some()); + let config = Config::load(&handle); let compositor_state = CompositorState::new::(dh); let corner_radius_state = CornerRadiusState::new::(dh); let data_device_state = DataDeviceState::new::(dh); @@ -695,7 +670,7 @@ impl State { let cursor_shape_manager_state = CursorShapeManagerState::new::(dh); let seat_state = SeatState::::new(); let viewporter_state = ViewporterState::new::(dh); - let wl_drm_state = None; + let wl_drm_state = WlDrmState::>::default(); let kde_decoration_state = KdeDecorationState::new::(dh, Mode::Client); let xdg_decoration_state = XdgDecorationState::new::(dh); let session_lock_manager_state = @@ -765,9 +740,6 @@ impl State { let dbus_state = DBusState::init(&handle); - let session_lock_layer_state = - SessionLockLayerState::new::(dh, client_not_sandboxed); - State { common: Common { config, @@ -782,11 +754,7 @@ impl State { clock, startup_done: Arc::new(AtomicBool::new(false)), should_stop: false, - kiosk_exit_code: None, gesture_state: None, - ei_seats: std::collections::HashMap::new(), - ei_keyboard_source: std::collections::HashMap::new(), - ei_pointer_buttons: std::collections::HashMap::new(), kiosk_child: None, theme: cosmic::theme::system_preference(), @@ -835,7 +803,6 @@ impl State { pointer_focus_state: None, dbus_state, keyboard_layout_state, - session_lock_layer_state, #[cfg(feature = "logind")] inhibit_lid_fd: None, @@ -974,8 +941,6 @@ impl Common { output: &Output, render_element_states: &RenderElementStates, ) { - // NOTE: Keep in sync with surface iteration in `render_input_order_internal` - let shell = self.shell.read(); let processor = |namespace: Option| { move |surface: &WlSurface, states: &SurfaceData| { @@ -989,11 +954,8 @@ impl Common { ); if let Some(output) = primary_scanout_output { with_fractional_scale(states, |fraction_scale| { - // The 1.0 clamp is a workaround for Chromium - // TODO: remove if Chromium ever gets fixed - fraction_scale.set_preferred_scale( - output.current_scale().fractional_scale().max(1.0), - ); + fraction_scale + .set_preferred_scale(output.current_scale().fractional_scale()); }); } } @@ -1082,8 +1044,6 @@ impl Common { render_element_states: &RenderElementStates, mut dmabuf_feedback: impl FnMut(DrmNode) -> Option, ) { - // NOTE: Keep in sync with surface iteration in `render_input_order_internal` - let shell = self.shell.read(); if let Some(session_lock) = shell.session_lock.as_ref() @@ -1101,7 +1061,10 @@ impl Common { surface, render_element_states, &feedback.render_feedback, - &feedback.primary_scanout_feedback, + feedback + .primary_scanout_feedback + .as_ref() + .unwrap_or(&feedback.render_feedback), ) }, ) @@ -1297,8 +1260,6 @@ impl Common { #[profiling::function] pub fn send_frames(&self, output: &Output, sequence: Option) { - // NOTE: Keep in sync with surface iteration in `render_input_order_internal` - let time = self.clock.now(); let should_send = |surface: &WlSurface, states: &SurfaceData| { // Do the standard primary scanout output check. For pointer surfaces it deduplicates @@ -1340,12 +1301,8 @@ 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, is_xwayland: bool) -> Option { - if is_xwayland { - Some(Duration::ZERO) - } else if session_holder.sessions().is_empty() - && session_holder.cursor_sessions().is_empty() - { + fn throttle(session_holder: &impl SessionHolder) -> Option { + if session_holder.sessions().is_empty() && session_holder.cursor_sessions().is_empty() { THROTTLE } else { SCREENCOPY_THROTTLE @@ -1381,8 +1338,7 @@ impl Common { && let Some(grab_state) = move_grab.lock().unwrap().as_ref() { for (window, _) in grab_state.element().windows() { - let throttle = throttle(&window, window.x11_surface().is_some()); - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } } @@ -1406,28 +1362,25 @@ impl Common { .mapped() .for_each(|mapped| { for (window, _) in mapped.windows() { - let throttle = throttle(&window, window.x11_surface().is_some()); - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } }); if let Some(active) = shell.active_space(output) { if let Some(fs) = active.get_fullscreen(shell.seats.last_active()) { - let throttle = throttle(&fs.surface, fs.surface.x11_surface().is_some()); - fs.surface.send_frame(output, time, throttle, should_send); + fs.surface + .send_frame(output, time, throttle(&fs.surface), should_send); } active.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { - let throttle = throttle(&window, window.x11_surface().is_some()); - window.send_frame(output, time, throttle, should_send); + window.send_frame(output, time, throttle(&window), should_send); } }); // other (throttled) windows active.minimized_windows.iter().for_each(|m| { for window in m.windows() { - let throttle = throttle(&window, window.x11_surface().is_some()); - window.send_frame(output, time, throttle, |_, _| None); + window.send_frame(output, time, throttle(&window), |_, _| None); } }); @@ -1437,25 +1390,18 @@ impl Common { .filter(|w| w.handle != active.handle) { if let Some(fs) = space.get_fullscreen(shell.seats.last_active()) { - let throttle = min( - throttle(space, false), - throttle(&fs.surface, fs.surface.x11_surface().is_some()), - ); + let throttle = min(throttle(space), throttle(&fs.surface)); fs.surface.send_frame(output, time, throttle, |_, _| None); } space.mapped().for_each(|mapped| { for (window, _) in mapped.windows() { - let throttle = min( - throttle(space, false), - throttle(&window, window.x11_surface().is_some()), - ); + let throttle = min(throttle(space), throttle(&window)); window.send_frame(output, time, throttle, |_, _| None); } }); space.minimized_windows.iter().for_each(|m| { for window in m.windows() { - let throttle = throttle(&window, window.x11_surface().is_some()); - window.send_frame(output, time, throttle, |_, _| None); + window.send_frame(output, time, throttle(&window), |_, _| None); } }) } diff --git a/src/utils/global.rs b/src/utils/global.rs deleted file mode 100644 index e309f68a..00000000 --- a/src/utils/global.rs +++ /dev/null @@ -1,28 +0,0 @@ -use std::time::Duration; - -use calloop::{ - LoopHandle, - timer::{TimeoutAction, Timer}, -}; -use smithay::reexports::wayland_server::DisplayHandle; -use wayland_backend::server::GlobalId; - -pub fn remove_global_with_timer( - dh: &DisplayHandle, - event_loop_handle: &LoopHandle, - id: GlobalId, -) { - dh.disable_global::(id.clone()); - let source = Timer::from_duration(Duration::from_secs(5)); - let dh = dh.clone(); - let res = event_loop_handle.insert_source(source, move |_, _, _state| { - dh.remove_global::(id.clone()); - TimeoutAction::Drop - }); - if let Err(err) = res { - tracing::error!( - "failed to insert timer source to destroy output global: {}", - err - ); - } -} diff --git a/src/utils/iced/mod.rs b/src/utils/iced/mod.rs index 4522644b..2bfe888d 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, InputTime, KeyState, TabletToolDescriptor}, + input::{ButtonState, KeyState}, renderer::{ ImportMem, element::{ @@ -45,23 +45,14 @@ use smithay::{ Seat, keyboard::{KeyboardTarget, KeysymHandle, ModifiersState}, pointer::{ - AxisFrame as PointerAxisFrame, ButtonEvent as PointerButtonEvent, - GestureHoldBeginEvent, GestureHoldEndEvent, GesturePinchBeginEvent, - GesturePinchEndEvent, GesturePinchUpdateEvent, GestureSwipeBeginEvent, - GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent as PointerMotionEvent, + AxisFrame, ButtonEvent, GestureHoldBeginEvent, GestureHoldEndEvent, + GesturePinchBeginEvent, GesturePinchEndEvent, GesturePinchUpdateEvent, + GestureSwipeBeginEvent, GestureSwipeEndEvent, GestureSwipeUpdateEvent, MotionEvent, PointerTarget, RelativeMotionEvent, }, - tablet::{ - Tablet, - tool::{ - AxisFrame as ToolAxisFrame, ButtonEvent as ToolButtonEvent, - DownEvent as ToolDownEvent, MotionEvent as ToolMotionEvent, TabletToolTarget, - UpEvent as ToolUpEvent, - }, - }, touch::{ - DownEvent as TouchDownEvent, FrameMarker, MotionEvent as TouchMotionEvent, - OrientationEvent, ShapeEvent, TouchTarget, UpEvent as TouchUpEvent, + DownEvent, FrameMarker, MotionEvent as TouchMotionEvent, OrientationEvent, ShapeEvent, + TouchTarget, UpEvent, }, }, output::Output, @@ -198,7 +189,6 @@ pub(crate) struct IcedElementInternal { touch_map: HashMap, last_touch_frame: Option, last_touch_serial: Option, - last_tablet_serial: Option, // iced theme: Theme, @@ -250,7 +240,6 @@ 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, @@ -278,7 +267,6 @@ 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", &"...") @@ -338,7 +326,6 @@ impl IcedElement

{ touch_map: HashMap::new(), last_touch_frame: None, last_touch_serial: None, - last_tablet_serial: None, theme, renderer, state, @@ -494,143 +481,12 @@ 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: &PointerMotionEvent, + event: &MotionEvent, ) { let mut internal = self.0.lock().unwrap(); internal @@ -651,7 +507,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &PointerMotionEvent, + event: &MotionEvent, ) { let mut internal = self.0.lock().unwrap(); let event_location = event.location.downscale(internal.additional_scale); @@ -676,7 +532,7 @@ impl PointerTarget for IcedEle &self, seat: &Seat, _data: &mut crate::state::State, - event: &PointerButtonEvent, + event: &ButtonEvent, ) { let mut internal = self.0.lock().unwrap(); let button = match event.button { @@ -697,7 +553,7 @@ impl PointerTarget for IcedEle &self, _seat: &Seat, _data: &mut crate::state::State, - frame: PointerAxisFrame, + frame: AxisFrame, ) { let mut internal = self.0.lock().unwrap(); internal @@ -725,7 +581,7 @@ impl PointerTarget for IcedEle _seat: &Seat, _data: &mut crate::state::State, _serial: Serial, - _time: InputTime, + _time: u32, ) { let mut internal = self.0.lock().unwrap(); internal @@ -797,7 +653,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &TouchDownEvent, + event: &DownEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); @@ -817,7 +673,7 @@ impl TouchTarget for IcedEleme &self, seat: &Seat, _data: &mut crate::state::State, - event: &TouchUpEvent, + event: &UpEvent, ) { let mut internal = self.0.lock().unwrap(); let id = Finger(i32::from(event.slot) as u64); @@ -928,7 +784,7 @@ impl KeyboardTarget for IcedEl _key: KeysymHandle<'_>, _state: KeyState, _serial: Serial, - _time: InputTime, + _time: u32, ) { // TODO convert keys } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 401597cc..ac1df019 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -4,7 +4,6 @@ pub mod env; mod ids; pub(crate) use self::ids::id_gen; pub mod geometry; -pub mod global; pub mod iced; pub mod prelude; pub mod quirks; diff --git a/src/wayland/handlers/compositor.rs b/src/wayland/handlers/compositor.rs index ed40448b..12bc2e56 100644 --- a/src/wayland/handlers/compositor.rs +++ b/src/wayland/handlers/compositor.rs @@ -3,12 +3,9 @@ use crate::{shell::grabs::SeatMoveGrabState, state::ClientState, utils::prelude::*}; use calloop::Interest; use smithay::{ - backend::{ - input::InputTime, - renderer::{ - element::{Kind, surface::KindEvaluation}, - utils::{on_commit_buffer_handler, with_renderer_surface_state}, - }, + backend::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}, @@ -328,11 +325,9 @@ impl CompositorHandler for State { } } else { std::mem::drop(shell); - seat.get_pointer().unwrap().unset_grab( - self, - SERIAL_COUNTER.next_serial(), - InputTime::now(), - ); + seat.get_pointer() + .unwrap() + .unset_grab(self, SERIAL_COUNTER.next_serial(), 0); return; } } diff --git a/src/wayland/handlers/corner_radius.rs b/src/wayland/handlers/corner_radius.rs index 1a541938..ded8d923 100644 --- a/src/wayland/handlers/corner_radius.rs +++ b/src/wayland/handlers/corner_radius.rs @@ -45,11 +45,18 @@ pub fn surface_corners(states: &SurfaceData, size: Size) -> Option ]) } -pub fn surface_padding(states: &SurfaceData) -> Option<[i32; 4]> { +pub fn surface_padding(states: &SurfaceData, size: Size) -> Option<[i32; 4]> { let mut guard = states.cached_state.get::(); let padding = guard.current().0?; - Some([padding.top, padding.right, padding.bottom, padding.left]) + + // 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), + ]) } pub fn pad_rect( diff --git a/src/wayland/handlers/decoration.rs b/src/wayland/handlers/decoration.rs index a1efbd0a..90ec5855 100644 --- a/src/wayland/handlers/decoration.rs +++ b/src/wayland/handlers/decoration.rs @@ -1,6 +1,5 @@ use std::{cell::RefCell, sync::Mutex}; -use cosmic_comp_config::DecorationPreference; use smithay::{ desktop::Window, reexports::{ @@ -21,7 +20,7 @@ use smithay::{ }; use wayland_backend::protocol::WEnum; -use crate::{shell::CosmicMapped, state::State}; +use crate::state::State; pub struct PreferredDecorationMode(RefCell>); @@ -30,7 +29,7 @@ impl PreferredDecorationMode { window .user_data() .get::() - .is_none_or(|mode| mode.0.borrow().is_none()) + .is_none() } pub fn mode(window: &Window) -> Option { @@ -54,72 +53,6 @@ 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 { @@ -134,7 +67,7 @@ impl XdgDecorationHandler for State { let mode = if mapped.is_stack() { XdgMode::ServerSide } else { - XdgMode::from_preference(self.default_decoration()) + XdgMode::ClientSide }; if let Some((window, _)) = mapped @@ -147,10 +80,6 @@ impl XdgDecorationHandler for State { }); toplevel.send_configure(); } - } else { - toplevel.with_pending_state(|state| { - state.decoration_mode = Some(XdgMode::from_preference(self.default_decoration())) - }) } } @@ -170,13 +99,6 @@ 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)); - } } } @@ -188,28 +110,11 @@ 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 = Some(mode); + state.decoration_mode = None; }); 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); - } } } } @@ -224,10 +129,10 @@ impl KdeDecorationHandler for State { if mapped.is_stack() { KdeMode::Server } else { - KdeMode::from_preference(self.default_decoration()) + KdeMode::Client } } else { - KdeMode::from_preference(self.default_decoration()) + KdeMode::Client }; with_states(surface, |states| { diff --git a/src/wayland/handlers/dmabuf.rs b/src/wayland/handlers/dmabuf.rs index 572fe01b..4d9732bb 100644 --- a/src/wayland/handlers/dmabuf.rs +++ b/src/wayland/handlers/dmabuf.rs @@ -40,7 +40,7 @@ impl DmabufHandler for State { fn new_surface_feedback( &mut self, surface: &WlSurface, - _global: &DmabufGlobal, + global: &DmabufGlobal, ) -> Option { let BackendData::Kms(kms) = &self.backend else { return None; @@ -57,7 +57,18 @@ impl DmabufHandler for State { f.ended_at.is_none() && f.surface.has_surface(surface, WindowSurfaceType::all()) }); - let node = kms.primary_node.read().unwrap().unwrap(); + let node = kms + .drm_devices + .values() + .find(|device| { + device + .socket + .as_ref() + .map(|s| &s.dmabuf_global == global) + .unwrap_or(false) + })? + .inner + .render_node; let kms_surface = kms .drm_devices .values() @@ -66,7 +77,9 @@ impl DmabufHandler for State { Some(with_states(surface, |data| { if is_fullscreen { - feedback.primary_scanout_feedback + feedback + .primary_scanout_feedback + .unwrap_or(feedback.render_feedback) } else if frame_time_filter_fn(data) == Kind::ScanoutCandidate { feedback .overlay_scanout_feedback diff --git a/src/wayland/handlers/fractional_scale.rs b/src/wayland/handlers/fractional_scale.rs index dcc8d7f9..aea0cc7e 100644 --- a/src/wayland/handlers/fractional_scale.rs +++ b/src/wayland/handlers/fractional_scale.rs @@ -49,10 +49,7 @@ impl FractionalScaleHandler for State { with_states(&surface, |states| { with_fractional_scale(states, |fractional_scale| { - // The 1.0 clamp is a workaround for Chromium - // TODO: remove if Chromium ever gets fixed - fractional_scale - .set_preferred_scale(output.current_scale().fractional_scale().max(1.0)); + fractional_scale.set_preferred_scale(output.current_scale().fractional_scale()); }); }); } diff --git a/src/wayland/handlers/keyboard_layout.rs b/src/wayland/handlers/keyboard_layout.rs index 2477f93b..ac1fda87 100644 --- a/src/wayland/handlers/keyboard_layout.rs +++ b/src/wayland/handlers/keyboard_layout.rs @@ -1,7 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-only -use smithay::input::keyboard::KeyboardHandle; - use crate::state::State; use crate::wayland::protocols::keyboard_layout::{KeyboardLayoutHandler, KeyboardLayoutState}; @@ -9,8 +7,4 @@ 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/output_configuration.rs b/src/wayland/handlers/output_configuration.rs index 4f7000fd..6ab678f5 100644 --- a/src/wayland/handlers/output_configuration.rs +++ b/src/wayland/handlers/output_configuration.rs @@ -230,16 +230,6 @@ impl State { state.common.output_configuration_state.update(); }); - // Output scale or geometry may have changed. EI absolute-pointer regions - // are immutable per device, so any connected EI client (e.g. an RDP server) - // keeps mapping with the old scale until it reconnects. Recreate the - // device with the updated region so the mapping tracks the change live. - // (drop the backend lock first: refresh borrows `self` immutably.) - drop(backend); - if !test_only { - crate::libei::refresh_absolute_pointer_regions(self); - } - true } } diff --git a/src/wayland/handlers/pointer_constraints.rs b/src/wayland/handlers/pointer_constraints.rs index 743b3b0b..9ce5f63a 100644 --- a/src/wayland/handlers/pointer_constraints.rs +++ b/src/wayland/handlers/pointer_constraints.rs @@ -5,10 +5,7 @@ use smithay::{ input::pointer::PointerHandle, reexports::wayland_server::protocol::wl_surface::WlSurface, utils::{Logical, Point}, - wayland::{ - pointer_constraints::{ConstraintRemove, PointerConstraintsHandler}, - seat::WaylandFocus, - }, + wayland::{pointer_constraints::PointerConstraintsHandler, seat::WaylandFocus}, }; pub use smithay::wayland::pointer_constraints::{PointerConstraintRef, with_pointer_constraint}; @@ -79,37 +76,23 @@ impl PointerConstraintsHandler for State { } } - 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; - }; + 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(); - if hint_surface == *surface { - self.apply_cursor_hint(surface, pointer, hint_location, Some(&constraint)); - seat.set_pointer_constraint_hint(None); - } + 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); } } } diff --git a/src/wayland/handlers/pointer_warp.rs b/src/wayland/handlers/pointer_warp.rs index 634817cf..971ab583 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, None); + self.apply_cursor_hint(&surface, &pointer_handle, pos); } } } diff --git a/src/wayland/handlers/session_lock.rs b/src/wayland/handlers/session_lock.rs index c4e93ec5..39e1e375 100644 --- a/src/wayland/handlers/session_lock.rs +++ b/src/wayland/handlers/session_lock.rs @@ -46,11 +46,6 @@ impl SessionLockHandler for State { let mut shell = self.common.shell.write(); shell.session_lock = None; - let seats = shell.seats.iter().cloned().collect::>(); - for seat in &seats { - self.common.idle_notifier_state.notify_activity(seat); - } - for output in shell.outputs() { self.backend.schedule_render(output); } diff --git a/src/wayland/handlers/tablet_manager.rs b/src/wayland/handlers/tablet_manager.rs index 7cf2b8cb..60469ba9 100644 --- a/src/wayland/handlers/tablet_manager.rs +++ b/src/wayland/handlers/tablet_manager.rs @@ -1,14 +1,12 @@ // SPDX-License-Identifier: GPL-3.0-only -use crate::{shell::focus::target::PointerFocusTarget, state::State}; +use crate::state::State; use smithay::{ backend::input::TabletToolDescriptor, input::pointer::CursorImageStatus, - input::tablet::TabletSeatHandler, + wayland::tablet_manager::TabletSeatHandler, }; impl TabletSeatHandler for State { - 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 b1616bca..3da39952 100644 --- a/src/wayland/handlers/toplevel_management.rs +++ b/src/wayland/handlers/toplevel_management.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: GPL-3.0-only use smithay::{ - backend::input::InputTime, desktop::{WindowSurfaceType, layer_map_for_output}, input::{Seat, pointer::MotionEvent}, output::Output, @@ -125,7 +124,7 @@ impl ToplevelManagementHandler for State { &MotionEvent { location: new_pos.to_f64().as_logical(), serial, - time: InputTime::now(), + time: self.common.clock.now().as_millis(), }, ); ptr.frame(self); diff --git a/src/wayland/handlers/xdg_activation.rs b/src/wayland/handlers/xdg_activation.rs index 38ba6219..ad8ce0d0 100644 --- a/src/wayland/handlers/xdg_activation.rs +++ b/src/wayland/handlers/xdg_activation.rs @@ -243,7 +243,7 @@ impl State { { for mapped in current_workspace .mapped() - .filter(|m| m.maximized_state.lock().unwrap().is_some() && *m != &element) + .filter(|m| m.maximized_state.lock().unwrap().is_some()) .cloned() .collect::>() .into_iter() diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index be7084dd..b8288019 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -1,15 +1,11 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::{ - shell::{ - CosmicSurface, PendingWindow, - focus::target::KeyboardFocusTarget, - grabs::{GrabType, ReleaseMode}, - }, + shell::{CosmicSurface, PendingWindow, focus::target::KeyboardFocusTarget, grabs::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, @@ -30,7 +26,6 @@ use smithay::{ }, }, }; -use smithay::{desktop::layer_map_for_output, input::tablet::TabletSeatTrait}; use std::cell::Cell; use tracing::warn; @@ -55,7 +50,6 @@ impl XdgShellHandler for State { surface, seat, fullscreen: None, - minimized: false, maximized: false, sticky: false, }) @@ -195,17 +189,12 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - match grab.grab_type() { - GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), - GrabType::Pointer => seat - .get_pointer() + if grab.is_touch_grab() { + seat.get_touch().unwrap().set_grab(self, grab, serial); + } else { + seat.get_pointer() .unwrap() - .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), + .set_grab(self, grab, serial, focus) } } } @@ -228,17 +217,12 @@ impl XdgShellHandler for State { true, ) { std::mem::drop(shell); - match grab.grab_type() { - GrabType::Touch => seat.get_touch().unwrap().set_grab(self, grab, serial), - GrabType::Pointer => seat - .get_pointer() + if grab.is_touch_grab() { + seat.get_touch().unwrap().set_grab(self, grab, serial) + } else { + seat.get_pointer() .unwrap() - .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), + .set_grab(self, grab, serial, focus) } } } @@ -349,15 +333,17 @@ impl XdgShellHandler for State { if let Some(ref grab) = grab { if grab.has_ended() { should_ungrab = true; - } else if let Some(target) = grab.current_grab() - && let Some(wl_surface) = target.wl_surface() - && (wl_surface.as_ref() == surface.wl_surface() - || smithay::desktop::PopupManager::popups_for_surface( - surface.wl_surface(), - ) - .any(|(p, _)| p.wl_surface() == wl_surface.as_ref())) - { - should_ungrab = true; + } else if let Some(target) = grab.current_grab() { + if let Some(wl_surface) = target.wl_surface() { + if wl_surface.as_ref() == surface.wl_surface() + || smithay::desktop::PopupManager::popups_for_surface( + surface.wl_surface(), + ) + .any(|(p, _)| p.wl_surface() == wl_surface.as_ref()) + { + should_ungrab = true; + } + } } } if should_ungrab { diff --git a/src/wayland/protocols/corner_radius.rs b/src/wayland/protocols/corner_radius.rs index 5c1a200c..be6f9ca0 100644 --- a/src/wayland/protocols/corner_radius.rs +++ b/src/wayland/protocols/corner_radius.rs @@ -5,19 +5,17 @@ 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::backend::renderer::buffer_dimensions; -use smithay::backend::renderer::utils::RendererSurfaceStateUserData; +use smithay::desktop::utils::bbox_from_surface_tree; 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, Rectangle}; +use smithay::utils::{HookId, Logical, Point, Rectangle}; +use smithay::wayland::compositor::Cacheable; 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, @@ -192,7 +190,7 @@ where let radius_exists = with_states(surface.wl_surface(), |surface_data| { let hook_id = surface_data .data_map - .get_or_insert_threadsafe(|| LayerHookId::new(None)); + .get_or_insert_threadsafe(|| ToplevelHookId::new(None)); let guard = hook_id.lock().unwrap(); guard.as_ref().map(|(_, t)| t.upgrade().is_ok()) }); @@ -657,6 +655,7 @@ 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 @@ -666,40 +665,8 @@ 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( - Rectangle::from_size(size), - padding.0.as_ref().unwrap_or(&empty), - ) else { + let Some(padded_box) = pad_rect(bbox, 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/drm.rs b/src/wayland/protocols/drm.rs index d2902c98..c86e5ff0 100644 --- a/src/wayland/protocols/drm.rs +++ b/src/wayland/protocols/drm.rs @@ -38,11 +38,7 @@ use smithay::{ }; use tracing::trace; -use std::{ - convert::TryFrom, - path::PathBuf, - sync::{Arc, Mutex}, -}; +use std::{convert::TryFrom, path::PathBuf, sync::Arc}; pub enum ImportError { Failed, @@ -56,28 +52,19 @@ pub trait DrmHandler { } } -#[derive(Debug)] -pub struct WlDrmState { - device: Arc>, - global: GlobalId, - _marker: std::marker::PhantomData, -} - -#[derive(Debug)] -pub struct DrmGlobalDeviceData { - formats: Vec, - path: PathBuf, -} +#[derive(Debug, Default)] +pub struct WlDrmState(std::marker::PhantomData); /// Data associated with a drm global. pub struct DrmGlobalData { filter: Box Fn(&'a Client) -> bool + Send + Sync>, + formats: Arc>, + device_path: PathBuf, dmabuf_global: DmabufGlobal, - device: Arc>, } pub struct DrmInstanceData { - device: Arc>, + formats: Arc>, dmabuf_global: DmabufGlobal, } @@ -99,24 +86,16 @@ where data_init: &mut DataInit<'_, D>, ) { let data = DrmInstanceData { - device: global_data.device.clone(), + formats: global_data.formats.clone(), dmabuf_global: global_data.dmabuf_global, }; let drm_instance = data_init.init(resource, data); - drm_instance.device( - global_data - .device - .lock() - .unwrap() - .path - .to_string_lossy() - .into_owned(), - ); + drm_instance.device(global_data.device_path.to_string_lossy().into_owned()); if drm_instance.version() >= 2 { drm_instance.capabilities(wl_drm::Capability::Prime as u32); } - for format in global_data.device.lock().unwrap().formats.iter() { + for format in global_data.formats.iter() { if let Ok(converted) = wl_drm::Format::try_from(*format as u32) { drm_instance.format(converted as u32); } @@ -169,7 +148,7 @@ where } => { let format = match Fourcc::try_from(format) { Ok(format) => { - if !data.device.lock().unwrap().formats.contains(&format) { + if !data.formats.contains(&format) { drm.post_error( wl_drm::Error::InvalidFormat, String::from("Format not advertised by wl_drm"), @@ -241,12 +220,13 @@ where } impl WlDrmState { - pub fn new( + pub fn create_global( + &mut self, display: &DisplayHandle, device_path: PathBuf, formats: FormatSet, dmabuf_global: &DmabufGlobal, - ) -> Self + ) -> GlobalId where D: GlobalDispatch + Dispatch @@ -254,16 +234,19 @@ impl WlDrmState { + DmabufHandler + 'static, { - Self::new_with_filter::(display, device_path, formats, dmabuf_global, |_| true) + self.create_global_with_filter::(display, device_path, formats, dmabuf_global, |_| { + true + }) } - pub fn new_with_filter( + pub fn create_global_with_filter( + &mut self, display: &DisplayHandle, device_path: PathBuf, formats: FormatSet, dmabuf_global: &DmabufGlobal, client_filter: F, - ) -> Self + ) -> GlobalId where D: GlobalDispatch + Dispatch @@ -272,45 +255,21 @@ impl WlDrmState { + 'static, F: for<'a> Fn(&'a Client) -> bool + Send + Sync + 'static, { - let device = Arc::new(Mutex::new(DrmGlobalDeviceData { - formats: formats + let formats = Arc::new( + formats .into_iter() .filter(|f| f.modifier == Modifier::Invalid) .map(|f| f.code) .collect(), - path: device_path, - })); - + ); let data = DrmGlobalData { filter: Box::new(client_filter), - device: device.clone(), + formats, + device_path, dmabuf_global: *dmabuf_global, }; - let global = display.create_global::(2, data); - - WlDrmState { - device, - global, - _marker: Default::default(), - } - } - - pub fn update_device(&mut self, device_path: PathBuf, formats: FormatSet) { - let new_device = DrmGlobalDeviceData { - formats: formats - .into_iter() - .filter(|f| f.modifier == Modifier::Invalid) - .map(|f| f.code) - .collect(), - path: device_path, - }; - - *self.device.lock().unwrap() = new_device; - } - - pub fn global(&self) -> &GlobalId { - &self.global + display.create_global::(2, data) } } diff --git a/src/wayland/protocols/keyboard_layout.rs b/src/wayland/protocols/keyboard_layout.rs index 8a8840b6..f3a44f0a 100644 --- a/src/wayland/protocols/keyboard_layout.rs +++ b/src/wayland/protocols/keyboard_layout.rs @@ -17,10 +17,8 @@ use smithay::{ use std::mem; use wayland_backend::server::{ClientId, GlobalId}; -pub trait KeyboardLayoutHandler: SeatHandler { +pub trait KeyboardLayoutHandler { fn keyboard_layout_state(&mut self) -> &mut KeyboardLayoutState; - /// Group has been changed through the protocol - fn group_changed(&mut self, keyboard: &KeyboardHandle); } #[derive(Debug)] @@ -59,7 +57,6 @@ 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/mod.rs b/src/wayland/protocols/mod.rs index 48aa8337..c6c0234a 100644 --- a/src/wayland/protocols/mod.rs +++ b/src/wayland/protocols/mod.rs @@ -8,7 +8,6 @@ pub mod keyboard_layout; pub mod output_configuration; pub mod output_power; pub mod overlap_notify; -pub mod session_lock_layer; pub mod toplevel_info; pub mod toplevel_management; pub mod workspace; diff --git a/src/wayland/protocols/output_configuration/mod.rs b/src/wayland/protocols/output_configuration/mod.rs index d413e634..4bd1c0bd 100644 --- a/src/wayland/protocols/output_configuration/mod.rs +++ b/src/wayland/protocols/output_configuration/mod.rs @@ -1,6 +1,9 @@ // SPDX-License-Identifier: GPL-3.0-only -use calloop::LoopHandle; +use calloop::{ + LoopHandle, + timer::{TimeoutAction, Timer}, +}; use cosmic_comp_config::output::comp::AdaptiveSync; use cosmic_protocols::output_management::v1::server::{ zcosmic_output_configuration_head_v1::ZcosmicOutputConfigurationHeadV1, @@ -27,7 +30,7 @@ use smithay::{ utils::{Logical, Physical, Point, Size, Transform}, wayland::output::WlOutputData, }; -use std::{convert::TryFrom, sync::Mutex}; +use std::{convert::TryFrom, sync::Mutex, time::Duration}; mod handlers; @@ -516,6 +519,26 @@ where } } +fn remove_global_with_timer( + dh: &DisplayHandle, + event_loop_handle: &LoopHandle, + id: GlobalId, +) { + dh.disable_global::(id.clone()); + let source = Timer::from_duration(Duration::from_secs(5)); + let dh = dh.clone(); + let res = event_loop_handle.insert_source(source, move |_, _, _state| { + dh.remove_global::(id.clone()); + TimeoutAction::Drop + }); + if let Err(err) = res { + tracing::error!( + "failed to insert timer source to destroy output global: {}", + err + ); + } +} + macro_rules! delegate_output_configuration { ($(@<$( $lt:tt $( : $clt:tt $(+ $dlt:tt )* )? ),+>)? $ty: ty) => { smithay::reexports::wayland_server::delegate_global_dispatch!($(@< $( $lt $( : $clt $(+ $dlt )* )? ),+ >)? $ty: [ @@ -555,4 +578,4 @@ macro_rules! delegate_output_configuration { } pub(crate) use delegate_output_configuration; -use crate::utils::{global::remove_global_with_timer, prelude::OutputExt}; +use crate::utils::prelude::OutputExt; diff --git a/src/wayland/protocols/session_lock_layer.rs b/src/wayland/protocols/session_lock_layer.rs deleted file mode 100644 index 85edda50..00000000 --- a/src/wayland/protocols/session_lock_layer.rs +++ /dev/null @@ -1,136 +0,0 @@ -use cosmic_protocols::session_lock_layer::v1::server::cosmic_session_lock_layer_manager_v1; -use smithay::{ - reexports::wayland_server::{ - Client, DataInit, Dispatch, DisplayHandle, GlobalDispatch, New, backend::GlobalId, - protocol::wl_surface, - }, - wayland::{ - Dispatch2, GlobalDispatch2, - compositor::{Cacheable, with_states}, - shell::wlr_layer::WlrLayerShellHandler, - }, -}; - -struct SessionLockLayerData; - -#[derive(Debug)] -pub struct SessionLockLayerState { - global: GlobalId, -} - -impl SessionLockLayerState { - pub fn new(dh: &DisplayHandle, client_filter: F) -> Self - where - F: for<'a> Fn(&'a Client) -> bool + Clone + Send + Sync + 'static, - D: GlobalDispatch< - cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, - SessionLockLayerGlobalData, - > + 'static, - { - let global = dh - .create_global::( - 1, - SessionLockLayerGlobalData { - filter: Box::new(client_filter.clone()), - }, - ); - Self { global } - } - - pub fn global_id(&self) -> GlobalId { - self.global.clone() - } -} - -#[doc(hidden)] -pub struct SessionLockLayerGlobalData { - filter: Box Fn(&'a Client) -> bool + Send + Sync>, -} - -impl GlobalDispatch2 - for SessionLockLayerGlobalData -where - D: Dispatch< - cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, - SessionLockLayerData, - >, -{ - fn bind( - &self, - _state: &mut D, - _handle: &DisplayHandle, - _client: &Client, - resource: New, - data_init: &mut DataInit<'_, D>, - ) { - data_init.init(resource, SessionLockLayerData); - } - - fn can_view(&self, client: &Client) -> bool { - (self.filter)(client) - } -} - -#[derive(Clone, Copy, Default)] -struct SessionLockLayerSurfaceData { - show_on_lock: bool, -} - -impl Cacheable for SessionLockLayerSurfaceData { - fn commit(&mut self, _dh: &DisplayHandle) -> Self { - *self - } - - fn merge_into(self, into: &mut Self, _dh: &DisplayHandle) { - *into = self; - } -} - -pub fn layer_show_on_lock(wl_surface: &wl_surface::WlSurface) -> bool { - with_states(wl_surface, |states| { - if states.cached_state.has::() { - let mut state = states.cached_state.get::(); - state.current().show_on_lock - } else { - false - } - }) -} - -impl Dispatch2 - for SessionLockLayerData -where - D: WlrLayerShellHandler, -{ - fn request( - &self, - state: &mut D, - _: &Client, - _: &cosmic_session_lock_layer_manager_v1::CosmicSessionLockLayerManagerV1, - request: cosmic_session_lock_layer_manager_v1::Request, - _: &DisplayHandle, - _: &mut DataInit<'_, D>, - ) { - let (layer, value) = match request { - cosmic_session_lock_layer_manager_v1::Request::SetShowOnLock { layer } => (layer, true), - cosmic_session_lock_layer_manager_v1::Request::UnsetShowOnLock { layer } => { - (layer, false) - } - cosmic_session_lock_layer_manager_v1::Request::Destroy => { - return; - } - _ => unreachable!(), - }; - - if let Some(layer) = state - .shell_state() - .layer_surfaces() - .find(|surface| surface.shell_surface() == &layer) - { - with_states(layer.wl_surface(), |states| { - let mut state = states.cached_state.get::(); - state.pending().show_on_lock = value; - }); - } - } -} diff --git a/src/wayland/protocols/toplevel_info.rs b/src/wayland/protocols/toplevel_info.rs index 3146adc3..2dc76347 100644 --- a/src/wayland/protocols/toplevel_info.rs +++ b/src/wayland/protocols/toplevel_info.rs @@ -418,12 +418,6 @@ 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 cc6be3b4..25b8b0e0 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -9,9 +9,7 @@ use std::{ use crate::{ backend::render::cursor::{Cursor, load_cursor_env, load_cursor_theme}, shell::{ - CosmicSurface, PendingWindow, Shell, - focus::target::KeyboardFocusTarget, - grabs::{GrabType, ReleaseMode}, + CosmicSurface, PendingWindow, Shell, focus::target::KeyboardFocusTarget, grabs::ReleaseMode, }, state::State, utils::prelude::*, @@ -22,7 +20,7 @@ use smithay::{ backend::{ allocator::Fourcc, drm::DrmNode, - input::{ButtonState, InputTime, KeyState, Keycode}, + input::{ButtonState, KeyState, Keycode}, renderer::{ Bind, Frame, Offscreen, Renderer, element::{ @@ -34,7 +32,7 @@ use smithay::{ }, }, desktop::space::SpaceElement, - input::{keyboard::ModifiersState, pointer::CursorIcon, tablet::TabletSeatTrait}, + input::{keyboard::ModifiersState, pointer::CursorIcon}, reexports::{wayland_server::Client, x11rb::protocol::xproto::Window as X11Window}, utils::{ Buffer as BufferCoords, Logical, Point, Rectangle, SERIAL_COUNTER, Serial, Size, Transform, @@ -117,7 +115,7 @@ impl State { &self.common.display_handle, None, std::iter::empty::<(OsString, OsString)>(), - ["-enable-ei-portal"], + std::iter::empty::(), true, Stdio::null(), Stdio::null(), @@ -396,9 +394,8 @@ impl Common { sym: Keysym, code: Keycode, state: KeyState, - modifiers: ModifiersState, serial: Serial, - time: InputTime, + time: u32, ) { let config = self.config.cosmic_conf.xwayland_eavesdropping.keyboard; if config == EavesdroppingKeyboardMode::None { @@ -421,6 +418,7 @@ impl Common { .last_active() .get_keyboard() .unwrap(); + let modifiers = keyboard.modifier_state(); let is_modifier = sym.is_modifier_key(); let xstate = self.xwayland_state.as_mut().unwrap(); @@ -460,7 +458,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.millis(), code.raw() - 8, state.into()); + wl_keyboard.key(serial.into(), time, code.raw() - 8, state.into()); if xstate.last_modifier_state != Some(modifiers) { xstate.last_modifier_state = Some(modifiers); wl_keyboard.modifiers( @@ -480,7 +478,7 @@ impl Common { button: u32, state: ButtonState, serial: Serial, - time: InputTime, + time: u32, ) { if !self.config.cosmic_conf.xwayland_eavesdropping.pointer { return; @@ -520,7 +518,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.millis(), button, state.into()); + wl_pointer.button(serial.into(), time, button, state.into()); } } @@ -810,7 +808,6 @@ 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 @@ -819,7 +816,6 @@ impl XwmHandler for State { { pending.seat = seat; pending.fullscreen = fullscreen; - pending.minimized = minimized; pending.maximized = maximized; } else { let surface = CosmicSurface::from(window); @@ -827,7 +823,6 @@ impl XwmHandler for State { surface, seat, fullscreen, - minimized, maximized, sticky: false, }) @@ -863,7 +858,7 @@ impl XwmHandler for State { if let Some(target) = res { let seat = shell.seats.last_active().clone(); std::mem::drop(shell); - Shell::set_focus_on_x11_map(self, &target, &seat, false); + Shell::set_focus(self, Some(&target), &seat, None, false); } } } @@ -1047,29 +1042,17 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - 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( + if grab.is_touch_grab() { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } else { + 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, - ), + ) } } } @@ -1090,29 +1073,17 @@ impl XwmHandler for State { true, ) { std::mem::drop(shell); - 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( + if grab.is_touch_grab() { + seat.get_touch() + .unwrap() + .set_grab(self, grab, SERIAL_COUNTER.next_serial()) + } else { + 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, - ), + ) } } }