From c07639097699f2011c05067f73c1507be3cda9af Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Mon, 15 Sep 2025 18:55:38 -0400 Subject: [PATCH] feat: shortcut key input --- Cargo.lock | 151 ++++++----- cosmic-settings/Cargo.toml | 3 + .../pages/input/keyboard/shortcuts/common.rs | 226 ++++++++++++++-- .../pages/input/keyboard/shortcuts/custom.rs | 242 ++++++++++++++++-- .../keyboard/shortcuts/manage_windows.rs | 19 +- .../input/keyboard/shortcuts/move_window.rs | 19 +- .../src/pages/input/keyboard/shortcuts/nav.rs | 19 +- .../pages/input/keyboard/shortcuts/system.rs | 19 +- .../pages/input/keyboard/shortcuts/tiling.rs | 19 +- 9 files changed, 589 insertions(+), 128 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40a3b29e..2d3d5bf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -502,20 +502,20 @@ dependencies = [ [[package]] name = "async-io" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" dependencies = [ - "async-lock 3.4.1", + "autocfg", "cfg-if", "concurrent-queue", "futures-io", "futures-lite 2.6.1", "parking", - "polling 3.10.0", + "polling 3.11.0", "rustix 1.1.2", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -557,12 +557,12 @@ dependencies = [ [[package]] name = "async-process" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00" +checksum = "fc50921ec0055cdd8a16de48773bfeec5c972598674347252c0399676be7da75" dependencies = [ "async-channel", - "async-io 2.5.0", + "async-io 2.6.0", "async-lock 3.4.1", "async-signal", "async-task", @@ -586,11 +586,11 @@ dependencies = [ [[package]] name = "async-signal" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1" +checksum = "43c070bbf59cd3570b6b2dd54cd772527c7c3620fce8be898406dd3ed6adc64c" dependencies = [ - "async-io 2.5.0", + "async-io 2.6.0", "async-lock 3.4.1", "atomic-waker", "cfg-if", @@ -599,7 +599,7 @@ dependencies = [ "rustix 1.1.2", "signal-hook-registry", "slab", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -1046,7 +1046,7 @@ checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ "bitflags 2.9.4", "log", - "polling 3.10.0", + "polling 3.11.0", "rustix 0.38.44", "slab", "thiserror 1.0.69", @@ -1059,7 +1059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb9f6e1368bd4621d2c86baa7e37de77a938adf5221e5dd3d6133340101b309e" dependencies = [ "bitflags 2.9.4", - "polling 3.10.0", + "polling 3.11.0", "rustix 1.1.2", "slab", "tracing", @@ -1517,7 +1517,7 @@ dependencies = [ [[package]] name = "cosmic-comp-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-comp#cd1117080c026da61f1c7e6be55f893b3a2f87ef" +source = "git+https://github.com/pop-os/cosmic-comp#b83e9f1d32f7d7b933c3fc8d45ed574d7440212a" dependencies = [ "cosmic-config", "input", @@ -1529,7 +1529,7 @@ dependencies = [ [[package]] name = "cosmic-config" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "atomicwrites", "cosmic-config-derive", @@ -1550,7 +1550,7 @@ dependencies = [ [[package]] name = "cosmic-config-derive" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "quote", "syn 2.0.106", @@ -1614,7 +1614,7 @@ dependencies = [ [[package]] name = "cosmic-panel-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#2bd1a6f8e42b3857853a23b097daf2ab45eb0e18" +source = "git+https://github.com/pop-os/cosmic-panel#9c315e4acb60876aa2faacfe5777855830e88d79" dependencies = [ "anyhow", "cosmic-config", @@ -1646,7 +1646,7 @@ source = "git+https://github.com/pop-os/cosmic-randr#bce9cdf2d447508d4e2d54a2be4 dependencies = [ "cosmic-protocols", "futures-lite 2.6.1", - "indexmap 2.11.1", + "indexmap 2.11.3", "tachyonix", "thiserror 2.0.16", "tokio", @@ -1707,7 +1707,7 @@ dependencies = [ "i18n-embed-fl", "icu", "image", - "indexmap 2.11.1", + "indexmap 2.11.3", "itertools 0.14.0", "itoa", "libcosmic", @@ -1737,6 +1737,7 @@ dependencies = [ "upower_dbus", "url", "xkb-data", + "xkeysym", "zbus 5.11.0", "zbus_polkit", ] @@ -1796,7 +1797,7 @@ dependencies = [ "cosmic-protocols", "futures", "iced_futures", - "indexmap 2.11.1", + "indexmap 2.11.3", "itertools 0.14.0", "libcosmic", "libpulse-binding", @@ -1870,7 +1871,7 @@ dependencies = [ [[package]] name = "cosmic-theme" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "almost", "cosmic-config", @@ -2743,9 +2744,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d7be93788013f265201256d58f04936a8079ad5dc898743aa20525f503b683" +checksum = "44f150ffc8782f35521cec2b23727707cb4045706ba3c854e86bef66b3a8cdbd" dependencies = [ "autocfg", "tokio", @@ -2937,7 +2938,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.5+wasi-0.2.4", + "wasi 0.14.7+wasi-0.2.4", ] [[package]] @@ -3100,9 +3101,9 @@ dependencies = [ [[package]] name = "harfrust" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406a98b615ed380f2195fa8fb2ed3083e64b2a6329d710e06f95a42466f0f0c4" +checksum = "75a4c970f1a00edc1626f1e3cc039492b15b73df28b9fff70f95404a571b4fae" dependencies = [ "bitflags 2.9.4", "bytemuck", @@ -3298,7 +3299,7 @@ dependencies = [ [[package]] name = "iced" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "dnd", "iced_accessibility", @@ -3316,7 +3317,7 @@ dependencies = [ [[package]] name = "iced_accessibility" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "accesskit", "accesskit_winit", @@ -3325,7 +3326,7 @@ dependencies = [ [[package]] name = "iced_core" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "bitflags 2.9.4", "bytes", @@ -3350,7 +3351,7 @@ dependencies = [ [[package]] name = "iced_futures" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "futures", "iced_core", @@ -3376,7 +3377,7 @@ dependencies = [ [[package]] name = "iced_graphics" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "bitflags 2.9.4", "bytemuck", @@ -3398,7 +3399,7 @@ dependencies = [ [[package]] name = "iced_renderer" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "iced_graphics", "iced_tiny_skia", @@ -3410,7 +3411,7 @@ dependencies = [ [[package]] name = "iced_runtime" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "bytes", "cosmic-client-toolkit", @@ -3426,7 +3427,7 @@ dependencies = [ [[package]] name = "iced_tiny_skia" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "bytemuck", "cosmic-text", @@ -3442,7 +3443,7 @@ dependencies = [ [[package]] name = "iced_wgpu" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "as-raw-xcb-connection", "bitflags 2.9.4", @@ -3473,7 +3474,7 @@ dependencies = [ [[package]] name = "iced_widget" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -3493,7 +3494,7 @@ dependencies = [ [[package]] name = "iced_winit" version = "0.14.0-dev" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "cosmic-client-toolkit", "dnd", @@ -4029,13 +4030,14 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921" +checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3" dependencies = [ "equivalent", "hashbrown 0.15.5", "serde", + "serde_core", ] [[package]] @@ -4548,7 +4550,7 @@ checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" [[package]] name = "libcosmic" version = "0.1.0" -source = "git+https://github.com/pop-os/libcosmic#b9a00c6e799b80154190f11943bb65c1fc4dc58b" +source = "git+https://github.com/pop-os/libcosmic#0e797b244043ee86610113d547950204258dea83" dependencies = [ "apply", "ashpd 0.12.0", @@ -4646,9 +4648,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.9.4", "libc", @@ -5045,7 +5047,7 @@ dependencies = [ "cfg_aliases 0.1.1", "codespan-reporting", "hexf-parse", - "indexmap 2.11.1", + "indexmap 2.11.3", "log", "rustc-hash 1.1.0", "spirv", @@ -5971,16 +5973,16 @@ dependencies = [ [[package]] name = "polling" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" dependencies = [ "cfg-if", "concurrent-queue", "hermit-abi 0.5.2", "pin-project-lite", "rustix 1.1.2", - "windows-sys 0.60.2", + "windows-sys 0.61.0", ] [[package]] @@ -6631,9 +6633,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.37.2" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d" +checksum = "c8975fc98059f365204d635119cf9c5a60ae67b841ed49b5422a9a7e56cdfac0" dependencies = [ "arrayvec", "borsh", @@ -6813,10 +6815,11 @@ checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" [[package]] name = "serde" -version = "1.0.219" +version = "1.0.224" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "6aaeb1e94f53b16384af593c71e20b095e958dab1d26939c1b70645c5cfbcc0b" dependencies = [ + "serde_core", "serde_derive", ] @@ -6832,11 +6835,20 @@ dependencies = [ "xml-rs", ] +[[package]] +name = "serde_core" +version = "1.0.224" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f39390fa6346e24defbcdd3d9544ba8a19985d0af74df8501fbfe9a64341ab" +dependencies = [ + "serde_derive", +] + [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.224" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "87ff78ab5e8561c9a675bfc1785cb07ae721f0ee53329a595cefd8c04c2ac4e0" dependencies = [ "proc-macro2", "quote", @@ -6845,15 +6857,16 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ - "indexmap 2.11.1", + "indexmap 2.11.3", "itoa", "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -6886,7 +6899,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.1", + "indexmap 2.11.3", "schemars 0.9.0", "schemars 1.0.4", "serde", @@ -7664,7 +7677,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.11.1", + "indexmap 2.11.3", "toml_datetime", "winnow 0.5.40", ] @@ -7675,7 +7688,7 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.1", + "indexmap 2.11.3", "serde", "serde_spanned", "toml_datetime", @@ -8040,18 +8053,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasi" -version = "0.14.5+wasi-0.2.4" +version = "0.14.7+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4" +checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c" dependencies = [ "wasip2", ] [[package]] name = "wasip2" -version = "1.0.0+wasi-0.2.4" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] @@ -8355,7 +8368,7 @@ dependencies = [ "bitflags 2.9.4", "cfg_aliases 0.1.1", "document-features", - "indexmap 2.11.1", + "indexmap 2.11.3", "log", "naga", "once_cell", @@ -9083,9 +9096,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "write16" @@ -9175,7 +9188,7 @@ dependencies = [ [[package]] name = "xdg-shell-wrapper-config" version = "0.1.0" -source = "git+https://github.com/pop-os/cosmic-panel#2bd1a6f8e42b3857853a23b097daf2ab45eb0e18" +source = "git+https://github.com/pop-os/cosmic-panel#9c315e4acb60876aa2faacfe5777855830e88d79" dependencies = [ "serde", "wayland-protocols-wlr", @@ -9347,9 +9360,9 @@ checksum = "2d07e46d035fb8e375b2ce63ba4e4ff90a7f73cf2ffb0138b29e1158d2eaadf7" dependencies = [ "async-broadcast 0.7.2", "async-executor", - "async-io 2.5.0", + "async-io 2.6.0", "async-lock 3.4.1", - "async-process 2.4.0", + "async-process 2.5.0", "async-recursion", "async-task", "async-trait", diff --git a/cosmic-settings/Cargo.toml b/cosmic-settings/Cargo.toml index 93907be9..119b5aa5 100644 --- a/cosmic-settings/Cargo.toml +++ b/cosmic-settings/Cargo.toml @@ -71,6 +71,7 @@ upower_dbus = { git = "https://github.com/pop-os/dbus-settings-bindings", option bluez-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings", optional = true } url = "2.5.7" xkb-data = "0.2.1" +xkeysym = { version = "0.2.0", optional = true } zbus = { version = "5.11.0", default-features = false, features = [ "tokio", ], optional = true } @@ -147,6 +148,8 @@ page-input = [ "dep:cosmic-comp-config", "dep:cosmic-settings-config", "dep:udev", + "dep:xkeysym", + "wayland", ] page-legacy-applications = ["dep:cosmic-comp-config"] page-networking = [ diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs index 3dc163c2..bd0bffbc 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/common.rs @@ -2,14 +2,17 @@ // SPDX-License-Identifier: GPL-3.0-only use cosmic::app::ContextDrawer; -use cosmic::iced::{Alignment, Length}; +use cosmic::iced::event::listen_with; +use cosmic::iced::keyboard::key::Named; +use cosmic::iced::keyboard::{Key, Location, Modifiers}; +use cosmic::iced::{self, Alignment, Length}; use cosmic::widget::{self, button, icon, settings, text}; -use cosmic::{Apply, Element, Task, theme}; +use cosmic::{Apply, Element, Task, iced_winit, theme}; use cosmic_config::{ConfigGet, ConfigSet}; use cosmic_settings_config::shortcuts::{self, Action, Binding, Shortcuts}; use cosmic_settings_page as page; use slab::Slab; -use slotmap::Key; +use slotmap::Key as SlotmapKey; use std::borrow::Cow; use std::str::FromStr; use std::{io, mem}; @@ -26,12 +29,18 @@ pub enum ShortcutMessage { ResetBindings, ShowShortcut(usize, String), SubmitBinding(usize), + Inhibited(bool), + ProtocolUnavailable, + ModifiersChanged(Modifiers), + KeyReleased(u32, Key, Location), + KeyPressed(u32, Key, Location, Modifiers), } #[derive(Debug)] pub struct ShortcutBinding { pub id: widget::Id, pub binding: Binding, + pub pending: Binding, pub input: String, pub is_default: bool, pub is_saved: bool, @@ -67,6 +76,7 @@ impl ShortcutModel { slab.insert(ShortcutBinding { id: widget::Id::unique(), binding: binding.clone(), + pending: binding.clone(), input: String::new(), is_default, is_saved: true, @@ -150,6 +160,7 @@ impl Model { pub(super) fn config_add(&self, action: Action, binding: Binding) { let mut shortcuts = self.shortcuts_config(); shortcuts.0.insert(binding, action); + self.shortcuts_config_set(shortcuts); } @@ -226,7 +237,7 @@ impl Model { None } - pub(super) fn on_enter(&mut self) { + pub(super) fn on_enter(&mut self) -> cosmic::Task { let mut shortcuts = self.config.get::("defaults").unwrap_or_default(); self.defaults = shortcuts.clone(); @@ -240,6 +251,8 @@ impl Model { self.shortcut_models = (self.actions)(&self.defaults, &shortcuts); self.shortcut_context = None; self.editing = None; + + return Task::none(); } pub(super) fn on_context_drawer_close(&mut self) { @@ -313,7 +326,10 @@ impl Model { self.editing = Some(binding_id); shortcut.input.clear(); - return widget::text_input::focus(shortcut.id.clone()); + return Task::batch(vec![ + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(true).discard(), + widget::text_input::focus(shortcut.id.clone()) + ]); } // Create a new input and focus it. @@ -321,16 +337,19 @@ impl Model { self.editing = Some(model.bindings.insert(ShortcutBinding { id: id.clone(), binding: Binding::default(), + pending: Binding::default(), input: String::new(), is_default: false, is_saved: false, })); - return widget::text_input::focus(id); + return Task::batch(vec![ + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(true).discard(), + widget::text_input::focus(id) + ]); } } } - ShortcutMessage::ApplyReplace => { if let Some((id, new_binding, ..)) = self.replace_dialog.take() { if let Some(short_id) = self.shortcut_context { @@ -368,11 +387,10 @@ impl Model { } } - self.on_enter(); + _ = self.on_enter(); } } } - ShortcutMessage::CancelReplace => { if let Some(((id, _, _, _), short_id)) = self.replace_dialog.take().zip(self.shortcut_context) @@ -385,7 +403,6 @@ impl Model { } } } - ShortcutMessage::DeleteBinding(id) => { if let Some(short_id) = self.shortcut_context { if let Some(model) = self.shortcut_models.get_mut(short_id) { @@ -398,41 +415,47 @@ impl Model { } } } - ShortcutMessage::DeleteShortcut(id) => { let model = self.shortcut_models.remove(id); for (_, shortcut) in model.bindings { self.config_remove(&shortcut.binding); } } - ShortcutMessage::EditBinding(id, enable) => { + if !enable && self.editing == Some(id) { + self.editing = None; + if let Some(short_id) = self.shortcut_context { + if let Some(model) = self.shortcut_models.get_mut(short_id) { + if let Some(shortcut) = model.bindings.get_mut(id) { + shortcut.pending = shortcut.binding.clone(); + } + } + } + return Task::batch(vec![ + cosmic::widget::text_input::focus(self.add_keybindings_button_id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard() + ]); + } if let Some(short_id) = self.shortcut_context { if let Some(model) = self.shortcut_models.get_mut(short_id) { if let Some(shortcut) = model.bindings.get_mut(id) { if enable { self.editing = Some(id); shortcut.input = shortcut.binding.to_string(); - return widget::text_input::select_all(shortcut.id.clone()); + return iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(true).discard(); } else if self.editing == Some(id) { self.editing = None; + return iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(); } } } } } - - ShortcutMessage::InputBinding(id, text) => { - if let Some(short_id) = self.shortcut_context { - if let Some(model) = self.shortcut_models.get_mut(short_id) { - if let Some(shortcut) = model.bindings.get_mut(id) { - shortcut.input = text; - } - } + ShortcutMessage::InputBinding(bind_id, ..) => { + if self.editing.is_none() { + return self.update(ShortcutMessage::EditBinding(bind_id, true)); } } - - // Removes all bindings from the active shortcut context, and reloads the shortcuts model. ShortcutMessage::ResetBindings => { if let Some(short_id) = self.shortcut_context { if let Some(model) = self.shortcut_models.get(short_id) { @@ -449,10 +472,9 @@ impl Model { } } - self.on_enter(); + _ = self.on_enter(); } } - ShortcutMessage::ShowShortcut(id, description) => { self.shortcut_context = Some(id); self.shortcut_title = description; @@ -472,13 +494,162 @@ impl Model { return Task::batch(tasks); } + ShortcutMessage::SubmitBinding(_) => {} + ShortcutMessage::ProtocolUnavailable => { + tracing::error!("shortcut inhibit protocol is unavailable"); + } + ShortcutMessage::Inhibited(v) => { + panic!("{}", v); + } + ShortcutMessage::ModifiersChanged(modifiers) => { + if let Some((short_id, id)) = self.shortcut_context.zip(self.editing) { + if let Some(model) = self.shortcut_models.get_mut(short_id) { + if let Some(shortcut) = model.bindings.get_mut(id) { + let mut cfg_modifiers = + cosmic_settings_config::shortcuts::Modifiers::new(); + if modifiers.alt() { + cfg_modifiers = cfg_modifiers.alt() + } + if modifiers.control() { + cfg_modifiers = cfg_modifiers.ctrl() + } + if modifiers.shift() { + cfg_modifiers = cfg_modifiers.shift() + } + if modifiers.logo() { + cfg_modifiers = cfg_modifiers.logo() + } + shortcut.pending.modifiers = cfg_modifiers; + + if shortcut.pending.keycode.is_none() && modifiers.is_empty() { + self.editing = None; + shortcut.input = String::new(); + return Task::batch(vec![ + cosmic::widget::text_input::focus(self.add_keybindings_button_id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard() + ]); + } + shortcut.input = shortcut.pending.to_string(); + } + } + } + } + ShortcutMessage::KeyReleased(keycode, _, _) => { + if let Some((short_id, id)) = self.shortcut_context.zip(self.editing) { + if let Some(model) = self.shortcut_models.get_mut(short_id) { + if let Some(shortcut) = model.bindings.get_mut(id) { + // if the currently selected shortcut matches, finish selecting shortcut + if shortcut.pending.key.is_some() + && shortcut.pending.keycode.is_some_and(|k| k == keycode) + { + if shortcut.pending.modifiers + != cosmic_settings_config::shortcuts::Modifiers::new() + { + shortcut.input = shortcut.pending.to_string(); + // XX for now avoid applying the keycode + shortcut.binding.keycode = None; + return Task::batch(vec![ + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(), + self.submit_binding(id) + ]); + } - ShortcutMessage::SubmitBinding(id) => return self.submit_binding(id), + return Task::batch(vec![ + cosmic::widget::text_input::focus(self.add_keybindings_button_id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard() + ]); + } + } + } + } + } + ShortcutMessage::KeyPressed(keycode, unmodified_keysym, location, modifiers) => { + if unmodified_keysym == Key::Named(Named::Escape) && modifiers.is_empty() { + if let Some((short_id, id)) = self.shortcut_context.zip(self.editing) { + if let Some(model) = self.shortcut_models.get_mut(short_id) { + if let Some(binding) = model.bindings.get_mut(id) { + binding.reset(); + self.editing = None; + return Task::batch(vec![ + cosmic::widget::text_input::focus(self.add_keybindings_button_id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard() + ]); + } + } + } + return Task::none(); + } + if let Some((short_id, id)) = self.shortcut_context.zip(self.editing) { + if let Some(model) = self.shortcut_models.get_mut(short_id) { + if let Some(shortcut) = model.bindings.get_mut(id) { + shortcut.pending.keycode = Some(keycode); + shortcut.pending.key = + iced_winit::platform_specific::wayland::keymap::key_to_keysym( + unmodified_keysym, + location, + ); + } + } + } + } } Task::none() } + #[cfg(feature = "wayland")] + pub(crate) fn subscription( + &self, + _core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + if self.editing.is_some() { + listen_with(|event, _, _| match event { + iced::event::Event::Keyboard(iced::keyboard::Event::KeyPressed { + key, + physical_key, + location, + modifiers, + .. + }) => { + use cosmic::iced::keyboard::{Key, key::Named}; + + if matches!( + key, + Key::Named(Named::Super | Named::Alt | Named::Control | Named::Shift) + ) { + return None; + } + cosmic::iced_winit::conversion::physical_to_scancode(physical_key) + .map(|code| ShortcutMessage::KeyPressed(code, key, location, modifiers)) + } + iced::event::Event::Keyboard(iced::keyboard::Event::KeyReleased { + key, + physical_key, + location, + .. + }) => { + use cosmic::iced::keyboard::{Key, key::Named}; + + if matches!( + key, + Key::Named(Named::Super | Named::Alt | Named::Control | Named::Shift) + ) { + return None; + } + cosmic::iced_winit::conversion::physical_to_scancode(physical_key) + .map(|code| ShortcutMessage::KeyReleased(code, key, location)) + } + iced::event::Event::Keyboard(iced::keyboard::Event::ModifiersChanged(e)) => { + Some(ShortcutMessage::ModifiersChanged(e)) + } + + _ => None, + }) + } else { + cosmic::iced::Subscription::none() + } + } + pub(super) fn view(&self) -> Element { self.shortcut_models .iter() @@ -535,7 +706,6 @@ impl Model { if let Some(model) = self.shortcut_models.get_mut(short_id) { if let Some(shortcut) = model.bindings.get_mut(id) { let prev_binding = mem::replace(&mut shortcut.binding, new_binding.clone()); - shortcut.is_saved = true; shortcut.input.clear(); @@ -544,7 +714,6 @@ impl Model { } let action = model.action.clone(); - if shortcut.is_default { self.config_add(Action::Disable, prev_binding); } else { @@ -604,6 +773,7 @@ fn context_drawer<'a>( ShortcutMessage::EditBinding(bind_id, enable) }) .select_on_focus(true) + .on_focus(ShortcutMessage::EditBinding(bind_id, true)) .on_input(move |text| ShortcutMessage::InputBinding(bind_id, text)) .on_unfocus(ShortcutMessage::SubmitBinding(bind_id)) .on_submit(move |_| ShortcutMessage::SubmitBinding(bind_id)) diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs index 3b1c5c5f..10680389 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/custom.rs @@ -6,14 +6,17 @@ use std::str::FromStr; use super::{ShortcutBinding, ShortcutMessage, ShortcutModel}; use cosmic::app::ContextDrawer; +use cosmic::iced::keyboard::key::Named; +use cosmic::iced::keyboard::{Key, Location, Modifiers}; use cosmic::iced::{Alignment, Length}; +use cosmic::iced_winit; use cosmic::widget::{self, button, icon}; use cosmic::{Apply, Element, Task}; use cosmic_settings_config::Binding; use cosmic_settings_config::shortcuts::{Action, Shortcuts}; use cosmic_settings_page::{self as page, Section, section}; use slab::Slab; -use slotmap::{Key, SlotMap}; +use slotmap::{Key as SlotKey, SlotMap}; pub struct Page { entity: page::Entity, @@ -63,6 +66,9 @@ pub enum Message { Shortcut(ShortcutMessage), /// Open the add shortcut context drawer ShortcutContext, + ModifiersChanged(Modifiers), + KeyReleased(u32, Key, Location), + KeyPressed(u32, Key, Location, Modifiers), } #[derive(Default)] @@ -72,6 +78,7 @@ struct AddShortcut { pub name: String, pub task: String, pub keys: Slab<(String, widget::Id)>, + pub binding: Binding, } impl AddShortcut { @@ -99,17 +106,19 @@ impl Page { self.add_shortcut.task = text; } - Message::KeyInput(id, text) => { - self.add_shortcut.keys[id].0 = text; - } + Message::KeyInput(..) => {} Message::KeyEditing(id, enable) => { if enable { - self.add_shortcut.editing = Some(id) + self.add_shortcut.editing = Some(id); + return iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(true).discard(); } else if self.add_shortcut.editing == Some(id) { - let task = self.add_keybinding(); self.add_shortcut.editing = None; - return task; + + return Task::batch(vec![ + widget::text_input::focus(widget::Id::unique()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(), + ]); } } @@ -151,11 +160,13 @@ impl Page { addable_bindings.push(binding); } - for binding in addable_bindings { + for mut binding in addable_bindings { + binding.keycode = None; self.add_shortcut(binding); } - self.model.on_enter(); + self.add_shortcut.binding = Default::default(); + _ = self.model.on_enter(); } Message::EditCombination => { @@ -164,6 +175,10 @@ impl Page { return Task::batch(vec![ widget::text_input::focus(id.clone()), widget::text_input::select_all(id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + true, + ) + .discard() ]); } } @@ -175,12 +190,14 @@ impl Page { } Message::ReplaceApply => { - if let Some((binding, ..)) = self.replace_dialog.pop() { + if let Some((mut binding, ..)) = self.replace_dialog.pop() { self.model.config_remove(&binding); + binding.keycode = None; self.add_shortcut(binding); if self.replace_dialog.is_empty() { - self.model.on_enter(); + self.add_shortcut = Default::default(); + _ = self.model.on_enter(); } } } @@ -188,7 +205,8 @@ impl Page { Message::ReplaceCancel => { _ = self.replace_dialog.pop(); if self.replace_dialog.is_empty() { - self.model.on_enter(); + self.add_shortcut = Default::default(); + _ = self.model.on_enter(); } } @@ -207,6 +225,112 @@ impl Page { widget::text_input::focus(self.name_id.clone()), ]); } + + Message::ModifiersChanged(modifiers) => { + if self.add_shortcut.active { + let mut cfg_modifiers = cosmic_settings_config::shortcuts::Modifiers::new(); + if modifiers.alt() { + cfg_modifiers = cfg_modifiers.alt() + } + if modifiers.control() { + cfg_modifiers = cfg_modifiers.ctrl() + } + if modifiers.shift() { + cfg_modifiers = cfg_modifiers.shift() + } + if modifiers.logo() { + cfg_modifiers = cfg_modifiers.logo() + } + self.add_shortcut.binding.modifiers = cfg_modifiers; + + if self.add_shortcut.binding.keycode.is_none() && modifiers.is_empty() { + self.add_shortcut = Default::default(); + self.add_shortcut = Default::default(); + _ = self.model.on_enter(); + + return Task::batch(vec![ + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard() + ]); + } + if let Some(k) = self + .add_shortcut + .keys + .get_mut(self.add_shortcut.editing.unwrap()) + { + k.0 = self.add_shortcut.binding.to_string(); + } + } + } + Message::KeyReleased(keycode, _, _) => { + // if the currently selected shortcut matches, finish selecting shortcut + if self.add_shortcut.editing.is_some() + && self.add_shortcut.active + && self.add_shortcut.binding.key.is_some() + && self + .add_shortcut + .binding + .keycode + .is_some_and(|k| k == keycode) + && self.add_shortcut.binding.modifiers + != cosmic_settings_config::shortcuts::Modifiers::new() + { + // XX for now avoid applying the keycode + let binding = Binding { + modifiers: self.add_shortcut.binding.modifiers.clone(), + key: self.add_shortcut.binding.key, + keycode: None, + description: None, + }; + let Some(k) = self + .add_shortcut + .keys + .get_mut(self.add_shortcut.editing.unwrap()) + else { + return iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(); + }; + k.0 = binding.to_string(); + + if self.add_shortcut.name.trim().is_empty() + || self.add_shortcut.task.trim().is_empty() + { + return Task::batch(vec![ + widget::text_input::focus(widget::Id::unique()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(), + ]); + } + self.add_shortcut(binding); + self.add_shortcut = Default::default(); + _ = self.model.on_enter(); + + return Task::batch(vec![ + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(), + ]); + } + } + Message::KeyPressed(keycode, unmodified_keysym, location, modifiers) => { + if unmodified_keysym == Key::Named(Named::Escape) && modifiers.is_empty() { + self.add_shortcut.editing = None; + return Task::batch(vec![ + widget::text_input::focus(widget::Id::unique()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts(false).discard(), + ]); + } + if self.add_shortcut.active { + self.add_shortcut.binding.keycode = Some(keycode); + self.add_shortcut.binding.key = + iced_winit::platform_specific::wayland::keymap::key_to_keysym( + unmodified_keysym, + location, + ); + if let Some(k) = self + .add_shortcut + .keys + .get_mut(self.add_shortcut.editing.unwrap()) + { + k.0 = self.add_shortcut.binding.to_string(); + } + } + } } Task::none() @@ -221,7 +345,13 @@ impl Page { binding.clear(); - return widget::text_input::focus(id.clone()); + return Task::batch(vec![ + widget::text_input::focus(id.clone()), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + true, + ) + .discard(), + ]); } let new_id = widget::Id::unique(); @@ -234,6 +364,10 @@ impl Page { Task::batch(vec![ widget::text_input::focus(new_id.clone()), widget::text_input::select_all(new_id), + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + true, + ) + .discard(), ]) } @@ -275,6 +409,7 @@ impl Page { self.add_shortcut.editing == Some(id), move |enable| Message::KeyEditing(id, enable), ) + .on_focus(Message::KeyEditing(id, true)) .select_on_focus(true) .padding([0, 12]) .on_input(move |input| Message::KeyInput(id, input)) @@ -381,13 +516,87 @@ impl page::Page for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + self.add_shortcut = Default::default(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + use cosmic::iced::{self, event::listen_with}; + + cosmic::iced::Subscription::batch(vec![ + if self.add_shortcut.active && self.add_shortcut.editing.is_some() { + listen_with(|event, _, _| match event { + iced::event::Event::Keyboard(iced::keyboard::Event::KeyPressed { + key, + physical_key, + location, + modifiers, + .. + }) => { + use cosmic::iced::keyboard::{Key, key::Named}; + if matches!( + key, + Key::Named(Named::Super | Named::Alt | Named::Control | Named::Shift) + ) { + return None; + } + cosmic::iced_winit::conversion::physical_to_scancode(physical_key).map( + |code| { + crate::pages::Message::CustomShortcuts(Message::KeyPressed( + code, key, location, modifiers, + )) + }, + ) + } + iced::event::Event::Keyboard(iced::keyboard::Event::KeyReleased { + key, + physical_key, + location, + .. + }) => { + use cosmic::iced::keyboard::{Key, key::Named}; + if matches!( + key, + Key::Named(Named::Super | Named::Alt | Named::Control | Named::Shift) + ) { + return None; + } + cosmic::iced_winit::conversion::physical_to_scancode(physical_key).map( + |code| { + crate::pages::Message::CustomShortcuts(Message::KeyReleased( + code, key, location, + )) + }, + ) + } + iced::event::Event::Keyboard(iced::keyboard::Event::ModifiersChanged(e)) => { + Some(crate::pages::Message::CustomShortcuts( + Message::ModifiersChanged(e), + )) + } + + _ => None, + }) + } else { + cosmic::iced::Subscription::none() + }, + self.model + .subscription(core) + .map(|m| crate::pages::Message::CustomShortcuts(Message::Shortcut(m))), + ]) } } @@ -406,6 +615,7 @@ fn bindings(_defaults: &Shortcuts, keybindings: &Shortcuts) -> Slab for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + cosmic::iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + self.model + .subscription(core) + .map(crate::pages::Message::ManageWindowShortcuts) } } diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/move_window.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/move_window.rs index 37293a87..47e521dc 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/move_window.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/move_window.rs @@ -64,13 +64,26 @@ impl page::Page for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + cosmic::iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + self.model + .subscription(core) + .map(crate::pages::Message::MoveWindowShortcuts) } } diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/nav.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/nav.rs index dc0bcc85..843973e4 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/nav.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/nav.rs @@ -65,13 +65,26 @@ impl page::Page for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + cosmic::iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + self.model + .subscription(core) + .map(crate::pages::Message::NavShortcuts) } } diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/system.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/system.rs index a88b2277..9dfa2eba 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/system.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/system.rs @@ -64,13 +64,26 @@ impl page::Page for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + cosmic::iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + self.model + .subscription(core) + .map(crate::pages::Message::SystemShortcuts) } } diff --git a/cosmic-settings/src/pages/input/keyboard/shortcuts/tiling.rs b/cosmic-settings/src/pages/input/keyboard/shortcuts/tiling.rs index d2ecc584..a22d999d 100644 --- a/cosmic-settings/src/pages/input/keyboard/shortcuts/tiling.rs +++ b/cosmic-settings/src/pages/input/keyboard/shortcuts/tiling.rs @@ -64,13 +64,26 @@ impl page::Page for Page { } fn on_enter(&mut self) -> Task { - self.model.on_enter(); + _ = self.model.on_enter(); Task::none() } fn on_leave(&mut self) -> Task { - self.model.on_clear(); - Task::none() + _ = self.model.on_clear(); + cosmic::iced_winit::platform_specific::commands::keyboard_shortcuts_inhibit::inhibit_shortcuts( + false, + ) + .discard() + } + + #[cfg(feature = "wayland")] + fn subscription( + &self, + core: &cosmic::Core, + ) -> cosmic::iced::Subscription { + self.model + .subscription(core) + .map(crate::pages::Message::TilingShortcuts) } }