feat: runtime configurable keybindings
This commit is contained in:
parent
62afa4cf61
commit
553c49b42b
25 changed files with 674 additions and 829 deletions
103
Cargo.lock
generated
103
Cargo.lock
generated
|
|
@ -425,6 +425,12 @@ version = "0.21.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.22.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit-set"
|
name = "bit-set"
|
||||||
version = "0.5.3"
|
version = "0.5.3"
|
||||||
|
|
@ -663,6 +669,7 @@ dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
|
"serde",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-targets 0.52.5",
|
"windows-targets 0.52.5",
|
||||||
]
|
]
|
||||||
|
|
@ -872,6 +879,7 @@ dependencies = [
|
||||||
"cosmic-comp-config",
|
"cosmic-comp-config",
|
||||||
"cosmic-config",
|
"cosmic-config",
|
||||||
"cosmic-protocols",
|
"cosmic-protocols",
|
||||||
|
"cosmic-settings-config",
|
||||||
"edid-rs",
|
"edid-rs",
|
||||||
"egui",
|
"egui",
|
||||||
"egui_plot",
|
"egui_plot",
|
||||||
|
|
@ -880,7 +888,7 @@ dependencies = [
|
||||||
"i18n-embed-fl",
|
"i18n-embed-fl",
|
||||||
"iced_tiny_skia",
|
"iced_tiny_skia",
|
||||||
"id_tree",
|
"id_tree",
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"keyframe",
|
"keyframe",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -967,6 +975,20 @@ dependencies = [
|
||||||
"wayland-server",
|
"wayland-server",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cosmic-settings-config"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/pop-os/cosmic-settings-daemon#ad0e0703549f7b135746d0429c6408cc8a7cc037"
|
||||||
|
dependencies = [
|
||||||
|
"cosmic-config",
|
||||||
|
"heck 0.5.0",
|
||||||
|
"serde",
|
||||||
|
"serde_with",
|
||||||
|
"thiserror",
|
||||||
|
"tracing",
|
||||||
|
"xkbcommon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cosmic-text"
|
name = "cosmic-text"
|
||||||
version = "0.12.0"
|
version = "0.12.0"
|
||||||
|
|
@ -1154,7 +1176,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
"lock_api",
|
"lock_api",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot_core 0.9.10",
|
"parking_lot_core 0.9.10",
|
||||||
|
|
@ -1179,6 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"powerfmt",
|
"powerfmt",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2190,7 +2213,7 @@ checksum = "cc11df1ace8e7e564511f53af41f3e42ddc95b56fd07b3f4445d2a6048bc682c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"gpu-descriptor-types",
|
"gpu-descriptor-types",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -2228,6 +2251,12 @@ dependencies = [
|
||||||
"crunchy",
|
"crunchy",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hashbrown"
|
||||||
|
version = "0.12.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.14.5"
|
version = "0.14.5"
|
||||||
|
|
@ -2259,6 +2288,12 @@ version = "0.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
|
|
@ -2607,6 +2642,17 @@ version = "0.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indexmap"
|
||||||
|
version = "1.9.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"hashbrown 0.12.3",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.2.6"
|
version = "2.2.6"
|
||||||
|
|
@ -2614,7 +2660,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3061,7 +3108,7 @@ version = "0.12.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3274,7 +3321,7 @@ dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
"hexf-parse",
|
"hexf-parse",
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"log",
|
"log",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"rustc-hash",
|
"rustc-hash",
|
||||||
|
|
@ -3791,7 +3838,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlv-list",
|
"dlv-list",
|
||||||
"hashbrown",
|
"hashbrown 0.14.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
@ -3821,7 +3868,7 @@ version = "0.17.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8"
|
checksum = "ec4c6225c69b4ca778c0aea097321a64c421cf4577b331c61b229267edabb6f8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck 0.4.1",
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
@ -4655,7 +4702,7 @@ version = "1.0.117"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
|
|
@ -4681,6 +4728,36 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with"
|
||||||
|
version = "3.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"chrono",
|
||||||
|
"hex",
|
||||||
|
"indexmap 1.9.3",
|
||||||
|
"indexmap 2.2.6",
|
||||||
|
"serde",
|
||||||
|
"serde_derive",
|
||||||
|
"serde_json",
|
||||||
|
"serde_with_macros",
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_with_macros"
|
||||||
|
version = "3.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2"
|
||||||
|
dependencies = [
|
||||||
|
"darling",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.66",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sha1"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
|
|
@ -4797,7 +4874,7 @@ dependencies = [
|
||||||
"gbm",
|
"gbm",
|
||||||
"gl_generator",
|
"gl_generator",
|
||||||
"glow 0.12.3",
|
"glow 0.12.3",
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"input",
|
"input",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
|
@ -5320,7 +5397,7 @@ version = "0.19.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow 0.5.40",
|
"winnow 0.5.40",
|
||||||
]
|
]
|
||||||
|
|
@ -5331,7 +5408,7 @@ version = "0.22.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
|
checksum = "c127785850e8c20836d49732ae6abfa47616e60bf9d9f57c43c250361a9db96c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned",
|
"serde_spanned",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
|
|
@ -6054,7 +6131,7 @@ dependencies = [
|
||||||
"bitflags 2.5.0",
|
"bitflags 2.5.0",
|
||||||
"cfg_aliases 0.1.1",
|
"cfg_aliases 0.1.1",
|
||||||
"codespan-reporting",
|
"codespan-reporting",
|
||||||
"indexmap",
|
"indexmap 2.2.6",
|
||||||
"log",
|
"log",
|
||||||
"naga",
|
"naga",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ calloop = {version = "0.14.0", features = ["executor"]}
|
||||||
cosmic-comp-config = {path = "cosmic-comp-config"}
|
cosmic-comp-config = {path = "cosmic-comp-config"}
|
||||||
cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]}
|
cosmic-config = {git = "https://github.com/pop-os/libcosmic/", features = ["calloop", "macro"]}
|
||||||
cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]}
|
cosmic-protocols = {git = "https://github.com/pop-os/cosmic-protocols", branch = "main", default-features = false, features = ["server"]}
|
||||||
|
cosmic-settings-config = { git = "https://github.com/pop-os/cosmic-settings-daemon" }
|
||||||
edid-rs = {version = "0.1"}
|
edid-rs = {version = "0.1"}
|
||||||
egui = {version = "0.23.0", optional = true}
|
egui = {version = "0.23.0", optional = true}
|
||||||
egui_plot = {version = "0.23.0", optional = true}
|
egui_plot = {version = "0.23.0", optional = true}
|
||||||
|
|
@ -45,7 +46,7 @@ serde_json = "1"
|
||||||
thiserror = "1.0.26"
|
thiserror = "1.0.26"
|
||||||
time = {version = "0.3.30", features = ["macros", "formatting", "local-offset"]}
|
time = {version = "0.3.30", features = ["macros", "formatting", "local-offset"]}
|
||||||
tiny-skia = "0.11"
|
tiny-skia = "0.11"
|
||||||
tracing = {version = "0.1.37", features = ["max_level_debug", "release_max_level_info"]}
|
tracing = { version = "0.1.37", features = ["max_level_debug", "release_max_level_info"] }
|
||||||
tracing-journald = "0.3.0"
|
tracing-journald = "0.3.0"
|
||||||
tracing-subscriber = {version = "0.3.16", features = ["env-filter", "tracing-log"]}
|
tracing-subscriber = {version = "0.3.16", features = ["env-filter", "tracing-log"]}
|
||||||
wayland-backend = "0.3.3"
|
wayland-backend = "0.3.3"
|
||||||
|
|
|
||||||
6
Makefile
6
Makefile
|
|
@ -5,7 +5,6 @@ libdir = $(prefix)/lib
|
||||||
sharedir = $(prefix)/share
|
sharedir = $(prefix)/share
|
||||||
|
|
||||||
BINARY = cosmic-comp
|
BINARY = cosmic-comp
|
||||||
ID = com.pop-os.Compositor
|
|
||||||
TARGET = debug
|
TARGET = debug
|
||||||
DEBUG ?= 0
|
DEBUG ?= 0
|
||||||
|
|
||||||
|
|
@ -23,6 +22,8 @@ endif
|
||||||
|
|
||||||
TARGET_BIN="$(DESTDIR)$(bindir)/$(BINARY)"
|
TARGET_BIN="$(DESTDIR)$(bindir)/$(BINARY)"
|
||||||
|
|
||||||
|
KEYBINDINGS_CONF="$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.Shortcuts/v1/defaults"
|
||||||
|
|
||||||
all: extract-vendor
|
all: extract-vendor
|
||||||
cargo build $(ARGS)
|
cargo build $(ARGS)
|
||||||
|
|
||||||
|
|
@ -46,6 +47,7 @@ endif
|
||||||
|
|
||||||
install:
|
install:
|
||||||
install -Dm0755 "target/$(TARGET)/$(BINARY)" "$(TARGET_BIN)"
|
install -Dm0755 "target/$(TARGET)/$(BINARY)" "$(TARGET_BIN)"
|
||||||
|
install -Dm0644 "data/keybindings.ron" "$(KEYBINDINGS_CONF)"
|
||||||
|
|
||||||
install-bare-session: install
|
install-bare-session: install
|
||||||
install -Dm0644 "data/cosmic.desktop" "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
|
install -Dm0644 "data/cosmic.desktop" "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
|
||||||
|
|
@ -55,7 +57,7 @@ install-bare-session: install
|
||||||
install -Dm0755 "data/cosmic-service" "$(DESTDIR)/$(bindir)/cosmic-service"
|
install -Dm0755 "data/cosmic-service" "$(DESTDIR)/$(bindir)/cosmic-service"
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm "$(TARGET_BIN)"
|
rm "$(TARGET_BIN)" "$(KEYBINDINGS_CONF)"
|
||||||
|
|
||||||
uninstall-bare-session:
|
uninstall-bare-session:
|
||||||
rm "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
|
rm "$(DESTDIR)$(sharedir)/wayland-sessions/cosmic.desktop"
|
||||||
95
config.ron
95
config.ron
|
|
@ -1,95 +0,0 @@
|
||||||
(
|
|
||||||
key_bindings: {
|
|
||||||
(modifiers: [Super, Shift], key: "Escape"): Terminate,
|
|
||||||
(modifiers: [Super, Ctrl], key: "Escape"): Debug,
|
|
||||||
(modifiers: [Super], key: "Escape"): Spawn("loginctl lock-session"),
|
|
||||||
(modifiers: [Super], key: "q"): Close,
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "1"): Workspace(1),
|
|
||||||
(modifiers: [Super], key: "2"): Workspace(2),
|
|
||||||
(modifiers: [Super], key: "3"): Workspace(3),
|
|
||||||
(modifiers: [Super], key: "4"): Workspace(4),
|
|
||||||
(modifiers: [Super], key: "5"): Workspace(5),
|
|
||||||
(modifiers: [Super], key: "6"): Workspace(6),
|
|
||||||
(modifiers: [Super], key: "7"): Workspace(7),
|
|
||||||
(modifiers: [Super], key: "8"): Workspace(8),
|
|
||||||
(modifiers: [Super], key: "9"): Workspace(9),
|
|
||||||
(modifiers: [Super], key: "0"): LastWorkspace,
|
|
||||||
(modifiers: [Super, Shift], key: "1"): MoveToWorkspace(1),
|
|
||||||
(modifiers: [Super, Shift], key: "2"): MoveToWorkspace(2),
|
|
||||||
(modifiers: [Super, Shift], key: "3"): MoveToWorkspace(3),
|
|
||||||
(modifiers: [Super, Shift], key: "4"): MoveToWorkspace(4),
|
|
||||||
(modifiers: [Super, Shift], key: "5"): MoveToWorkspace(5),
|
|
||||||
(modifiers: [Super, Shift], key: "6"): MoveToWorkspace(6),
|
|
||||||
(modifiers: [Super, Shift], key: "7"): MoveToWorkspace(7),
|
|
||||||
(modifiers: [Super, Shift], key: "8"): MoveToWorkspace(8),
|
|
||||||
(modifiers: [Super, Shift], key: "9"): MoveToWorkspace(9),
|
|
||||||
(modifiers: [Super, Shift], key: "0"): MoveToLastWorkspace,
|
|
||||||
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "Left"): MoveToOutput(Left),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "Down"): MoveToOutput(Down),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "Up"): MoveToOutput(Up),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "Right"): MoveToOutput(Right),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "h"): MoveToOutput(Left),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "k"): MoveToOutput(Down),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "j"): MoveToOutput(Up),
|
|
||||||
(modifiers: [Super, Ctrl, Alt], key: "l"): MoveToOutput(Right),
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "Period"): NextOutput,
|
|
||||||
(modifiers: [Super], key: "Comma"): PreviousOutput,
|
|
||||||
(modifiers: [Super, Shift], key: "Period"): MoveToNextOutput,
|
|
||||||
(modifiers: [Super, Shift], key: "Comma"): MoveToPreviousOutput,
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "Left"): Focus(Left),
|
|
||||||
(modifiers: [Super], key: "Right"): Focus(Right),
|
|
||||||
(modifiers: [Super], key: "Up"): Focus(Up),
|
|
||||||
(modifiers: [Super], key: "Down"): Focus(Down),
|
|
||||||
(modifiers: [Super], key: "h"): Focus(Left),
|
|
||||||
(modifiers: [Super], key: "j"): Focus(Down),
|
|
||||||
(modifiers: [Super], key: "k"): Focus(Up),
|
|
||||||
(modifiers: [Super], key: "l"): Focus(Right),
|
|
||||||
(modifiers: [Super], key: "u"): Focus(Out),
|
|
||||||
(modifiers: [Super], key: "i"): Focus(In),
|
|
||||||
|
|
||||||
(modifiers: [Super, Shift], key: "Left"): Move(Left),
|
|
||||||
(modifiers: [Super, Shift], key: "Right"): Move(Right),
|
|
||||||
(modifiers: [Super, Shift], key: "Up"): Move(Up),
|
|
||||||
(modifiers: [Super, Shift], key: "Down"): Move(Down),
|
|
||||||
(modifiers: [Super, Shift], key: "h"): Move(Left),
|
|
||||||
(modifiers: [Super, Shift], key: "j"): Move(Down),
|
|
||||||
(modifiers: [Super, Shift], key: "k"): Move(Up),
|
|
||||||
(modifiers: [Super, Shift], key: "l"): Move(Right),
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "o"): ToggleOrientation,
|
|
||||||
(modifiers: [Super], key: "s"): ToggleStacking,
|
|
||||||
(modifiers: [Super], key: "y"): ToggleTiling,
|
|
||||||
(modifiers: [Super], key: "g"): ToggleWindowFloating,
|
|
||||||
(modifiers: [Super], key: "x"): SwapWindow,
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "m"): Maximize,
|
|
||||||
(modifiers: [Super], key: "r"): Resizing(Outwards),
|
|
||||||
(modifiers: [Super, Shift], key: "r"): Resizing(Inwards),
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "b"): Spawn("xdg-open http://"),
|
|
||||||
(modifiers: [Super], key: "f"): Spawn("xdg-open ~"),
|
|
||||||
//TODO: ability to select default terminal
|
|
||||||
(modifiers: [Super], key: "t"): Spawn("cosmic-term"),
|
|
||||||
|
|
||||||
(modifiers: [Super], key: "a"): Spawn("cosmic-app-library"),
|
|
||||||
(modifiers: [Super], key: "w"): Spawn("cosmic-workspaces"),
|
|
||||||
(modifiers: [Super], key: "slash"): Spawn("cosmic-launcher"),
|
|
||||||
(modifiers: [Super]): Spawn("cosmic-launcher"),
|
|
||||||
(modifiers: [Alt], key: "Tab"): Spawn("cosmic-launcher alt-tab"),
|
|
||||||
(modifiers: [Super], key: "Tab"): Spawn("cosmic-launcher alt-tab"),
|
|
||||||
|
|
||||||
(modifiers: [], key: "Print"): Spawn("cosmic-screenshot"),
|
|
||||||
|
|
||||||
(modifiers: [], key: "XF86AudioRaiseVolume"): Spawn("amixer sset Master 5%+"),
|
|
||||||
(modifiers: [], key: "XF86AudioLowerVolume"): Spawn("amixer sset Master 5%-"),
|
|
||||||
(modifiers: [], key: "XF86AudioMute"): Spawn("amixer sset Master toggle"),
|
|
||||||
(modifiers: [], key: "XF86AudioMicMute"): Spawn("amixer sset Capture toggle"),
|
|
||||||
(modifiers: [], key: "XF86MonBrightnessUp"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon IncreaseDisplayBrightness"),
|
|
||||||
(modifiers: [], key: "XF86MonBrightnessDown"): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon DecreaseDisplayBrightness"),
|
|
||||||
},
|
|
||||||
data_control_enabled: false,
|
|
||||||
)
|
|
||||||
90
data/keybindings.ron
Normal file
90
data/keybindings.ron
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
{
|
||||||
|
(modifiers: [Super, Shift], key: "Escape"): Terminate,
|
||||||
|
(modifiers: [Super, Ctrl], key: "Escape"): Debug,
|
||||||
|
(modifiers: [Super], key: "Escape"): System(LockScreen),
|
||||||
|
(modifiers: [Super], key: "q"): Close,
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "1"): Workspace(1),
|
||||||
|
(modifiers: [Super], key: "2"): Workspace(2),
|
||||||
|
(modifiers: [Super], key: "3"): Workspace(3),
|
||||||
|
(modifiers: [Super], key: "4"): Workspace(4),
|
||||||
|
(modifiers: [Super], key: "5"): Workspace(5),
|
||||||
|
(modifiers: [Super], key: "6"): Workspace(6),
|
||||||
|
(modifiers: [Super], key: "7"): Workspace(7),
|
||||||
|
(modifiers: [Super], key: "8"): Workspace(8),
|
||||||
|
(modifiers: [Super], key: "9"): Workspace(9),
|
||||||
|
(modifiers: [Super], key: "0"): LastWorkspace,
|
||||||
|
(modifiers: [Super, Shift], key: "1"): MoveToWorkspace(1),
|
||||||
|
(modifiers: [Super, Shift], key: "2"): MoveToWorkspace(2),
|
||||||
|
(modifiers: [Super, Shift], key: "3"): MoveToWorkspace(3),
|
||||||
|
(modifiers: [Super, Shift], key: "4"): MoveToWorkspace(4),
|
||||||
|
(modifiers: [Super, Shift], key: "5"): MoveToWorkspace(5),
|
||||||
|
(modifiers: [Super, Shift], key: "6"): MoveToWorkspace(6),
|
||||||
|
(modifiers: [Super, Shift], key: "7"): MoveToWorkspace(7),
|
||||||
|
(modifiers: [Super, Shift], key: "8"): MoveToWorkspace(8),
|
||||||
|
(modifiers: [Super, Shift], key: "9"): MoveToWorkspace(9),
|
||||||
|
(modifiers: [Super, Shift], key: "0"): MoveToLastWorkspace,
|
||||||
|
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "Left"): MoveToOutput(Left),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "Down"): MoveToOutput(Down),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "Up"): MoveToOutput(Up),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "Right"): MoveToOutput(Right),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "h"): MoveToOutput(Left),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "k"): MoveToOutput(Down),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "j"): MoveToOutput(Up),
|
||||||
|
(modifiers: [Super, Ctrl, Alt], key: "l"): MoveToOutput(Right),
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "Period"): NextOutput,
|
||||||
|
(modifiers: [Super], key: "Comma"): PreviousOutput,
|
||||||
|
(modifiers: [Super, Shift], key: "Period"): MoveToNextOutput,
|
||||||
|
(modifiers: [Super, Shift], key: "Comma"): MoveToPreviousOutput,
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "Left"): Focus(Left),
|
||||||
|
(modifiers: [Super], key: "Right"): Focus(Right),
|
||||||
|
(modifiers: [Super], key: "Up"): Focus(Up),
|
||||||
|
(modifiers: [Super], key: "Down"): Focus(Down),
|
||||||
|
(modifiers: [Super], key: "h"): Focus(Left),
|
||||||
|
(modifiers: [Super], key: "j"): Focus(Down),
|
||||||
|
(modifiers: [Super], key: "k"): Focus(Up),
|
||||||
|
(modifiers: [Super], key: "l"): Focus(Right),
|
||||||
|
(modifiers: [Super], key: "u"): Focus(Out),
|
||||||
|
(modifiers: [Super], key: "i"): Focus(In),
|
||||||
|
|
||||||
|
(modifiers: [Super, Shift], key: "Left"): Move(Left),
|
||||||
|
(modifiers: [Super, Shift], key: "Right"): Move(Right),
|
||||||
|
(modifiers: [Super, Shift], key: "Up"): Move(Up),
|
||||||
|
(modifiers: [Super, Shift], key: "Down"): Move(Down),
|
||||||
|
(modifiers: [Super, Shift], key: "h"): Move(Left),
|
||||||
|
(modifiers: [Super, Shift], key: "j"): Move(Down),
|
||||||
|
(modifiers: [Super, Shift], key: "k"): Move(Up),
|
||||||
|
(modifiers: [Super, Shift], key: "l"): Move(Right),
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "o"): ToggleOrientation,
|
||||||
|
(modifiers: [Super], key: "s"): ToggleStacking,
|
||||||
|
(modifiers: [Super], key: "y"): ToggleTiling,
|
||||||
|
(modifiers: [Super], key: "g"): ToggleWindowFloating,
|
||||||
|
(modifiers: [Super], key: "x"): SwapWindow,
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "m"): Maximize,
|
||||||
|
(modifiers: [Super], key: "r"): Resizing(Outwards),
|
||||||
|
(modifiers: [Super, Shift], key: "r"): Resizing(Inwards),
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "b"): System(WebBrowser),
|
||||||
|
(modifiers: [Super], key: "f"): System(HomeFolder),
|
||||||
|
(modifiers: [Super], key: "t"): System(Terminal),
|
||||||
|
|
||||||
|
(modifiers: [Super], key: "a"): System(AppLibrary),
|
||||||
|
(modifiers: [Super], key: "w"): System(WorkspaceOverview),
|
||||||
|
(modifiers: [Super], key: "slash"): System(Launcher),
|
||||||
|
(modifiers: [Super]): System(Launcher),
|
||||||
|
(modifiers: [Alt], key: "Tab"): System(WindowSwitcher),
|
||||||
|
(modifiers: [Super], key: "Tab"): System(WindowSwitcher),
|
||||||
|
|
||||||
|
(modifiers: [], key: "Print"): System(Screenshot),
|
||||||
|
(modifiers: [], key: "XF86AudioRaiseVolume"): System(VolumeRaise),
|
||||||
|
(modifiers: [], key: "XF86AudioLowerVolume"): System(VolumeLower),
|
||||||
|
(modifiers: [], key: "XF86AudioMute"): System(Mute),
|
||||||
|
(modifiers: [], key: "XF86AudioMicMute"): System(MuteMic),
|
||||||
|
(modifiers: [], key: "XF86MonBrightnessUp"): System(BrightnessUp),
|
||||||
|
(modifiers: [], key: "XF86MonBrightnessDown"): System(BrightnessDown),
|
||||||
|
}
|
||||||
1
debian/cosmic-comp.install
vendored
1
debian/cosmic-comp.install
vendored
|
|
@ -1 +0,0 @@
|
||||||
config.ron etc/cosmic-comp
|
|
||||||
|
|
@ -1,221 +1,29 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
|
||||||
|
|
||||||
use crate::shell::{focus::FocusDirection, grabs::ResizeEdge, Direction, ResizeDirection};
|
|
||||||
use cosmic_comp_config::workspace::WorkspaceLayout;
|
use cosmic_comp_config::workspace::WorkspaceLayout;
|
||||||
use serde::Deserialize;
|
use cosmic_settings_config::shortcuts::State as KeyState;
|
||||||
use smithay::{
|
use cosmic_settings_config::shortcuts::{self, Modifiers, Shortcuts};
|
||||||
backend::input::KeyState,
|
use smithay::input::keyboard::ModifiersState;
|
||||||
input::keyboard::{xkb::keysym_get_name, ModifiersState},
|
use xkbcommon::xkb;
|
||||||
};
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use super::types::*;
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
|
||||||
pub enum KeyModifier {
|
|
||||||
Ctrl,
|
|
||||||
Alt,
|
|
||||||
Shift,
|
|
||||||
Super,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
|
|
||||||
pub struct KeyModifiers {
|
|
||||||
pub ctrl: bool,
|
|
||||||
pub alt: bool,
|
|
||||||
pub shift: bool,
|
|
||||||
pub logo: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PartialEq<ModifiersState> for KeyModifiers {
|
|
||||||
fn eq(&self, other: &ModifiersState) -> bool {
|
|
||||||
self.ctrl == other.ctrl
|
|
||||||
&& self.alt == other.alt
|
|
||||||
&& self.shift == other.shift
|
|
||||||
&& self.logo == other.logo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<KeyModifiers> for ModifiersState {
|
|
||||||
fn into(self) -> KeyModifiers {
|
|
||||||
KeyModifiers {
|
|
||||||
ctrl: self.ctrl,
|
|
||||||
alt: self.alt,
|
|
||||||
shift: self.shift,
|
|
||||||
logo: self.logo,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::AddAssign<KeyModifier> for KeyModifiers {
|
|
||||||
fn add_assign(&mut self, rhs: KeyModifier) {
|
|
||||||
match rhs {
|
|
||||||
KeyModifier::Ctrl => self.ctrl = true,
|
|
||||||
KeyModifier::Alt => self.alt = true,
|
|
||||||
KeyModifier::Shift => self.shift = true,
|
|
||||||
KeyModifier::Super => self.logo = true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::BitOr for KeyModifier {
|
|
||||||
type Output = KeyModifiers;
|
|
||||||
|
|
||||||
fn bitor(self, rhs: KeyModifier) -> Self::Output {
|
|
||||||
let mut modifiers = self.into();
|
|
||||||
modifiers += rhs;
|
|
||||||
modifiers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Into<KeyModifiers> for KeyModifier {
|
|
||||||
fn into(self) -> KeyModifiers {
|
|
||||||
let mut modifiers = KeyModifiers {
|
|
||||||
ctrl: false,
|
|
||||||
alt: false,
|
|
||||||
shift: false,
|
|
||||||
logo: false,
|
|
||||||
};
|
|
||||||
modifiers += self;
|
|
||||||
modifiers
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Describtion of a key combination that might be
|
|
||||||
/// handled by the compositor.
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Hash)]
|
|
||||||
#[serde(deny_unknown_fields)]
|
|
||||||
pub struct KeyPattern {
|
|
||||||
/// What modifiers are expected to be pressed alongside the key
|
|
||||||
#[serde(deserialize_with = "deserialize_KeyModifiers")]
|
|
||||||
pub modifiers: KeyModifiers,
|
|
||||||
/// The actual key, that was pressed
|
|
||||||
#[serde(deserialize_with = "deserialize_Keysym", default)]
|
|
||||||
pub key: Option<Keysym>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl KeyPattern {
|
|
||||||
pub fn new(modifiers: impl Into<KeyModifiers>, key: Option<Keysym>) -> KeyPattern {
|
|
||||||
KeyPattern {
|
|
||||||
modifiers: modifiers.into(),
|
|
||||||
key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn inferred_direction(&self) -> Option<Direction> {
|
|
||||||
match self.key? {
|
|
||||||
Keysym::Left | Keysym::h | Keysym::H => Some(Direction::Left),
|
|
||||||
Keysym::Down | Keysym::j | Keysym::J => Some(Direction::Down),
|
|
||||||
Keysym::Up | Keysym::k | Keysym::K => Some(Direction::Up),
|
|
||||||
Keysym::Right | Keysym::l | Keysym::L => Some(Direction::Right),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for KeyPattern {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
let mut result = String::new();
|
|
||||||
if self.modifiers.logo {
|
|
||||||
result += "Super+";
|
|
||||||
}
|
|
||||||
if self.modifiers.ctrl {
|
|
||||||
result += "Ctrl+";
|
|
||||||
}
|
|
||||||
if self.modifiers.alt {
|
|
||||||
result += "Alt+";
|
|
||||||
}
|
|
||||||
if self.modifiers.shift {
|
|
||||||
result += "Shift+";
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(key) = self.key {
|
|
||||||
result += &keysym_get_name(key);
|
|
||||||
} else {
|
|
||||||
result.remove(result.len() - 1);
|
|
||||||
}
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
|
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
Terminate,
|
/// Behaviors managed internally by cosmic-comp.
|
||||||
Debug,
|
Private(PrivateAction),
|
||||||
Close,
|
/// Behaviors managed via cosmic-settings.
|
||||||
#[serde(skip)]
|
Shortcut(shortcuts::Action),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
// Behaviors which are internally defined and emitted.
|
||||||
|
pub enum PrivateAction {
|
||||||
Escape,
|
Escape,
|
||||||
|
Resizing(
|
||||||
Workspace(u8),
|
shortcuts::action::ResizeDirection,
|
||||||
NextWorkspace,
|
shortcuts::action::ResizeEdge,
|
||||||
PreviousWorkspace,
|
shortcuts::State,
|
||||||
LastWorkspace,
|
),
|
||||||
MoveToWorkspace(u8),
|
|
||||||
MoveToNextWorkspace,
|
|
||||||
MoveToPreviousWorkspace,
|
|
||||||
MoveToLastWorkspace,
|
|
||||||
SendToWorkspace(u8),
|
|
||||||
SendToNextWorkspace,
|
|
||||||
SendToPreviousWorkspace,
|
|
||||||
SendToLastWorkspace,
|
|
||||||
|
|
||||||
NextOutput,
|
|
||||||
PreviousOutput,
|
|
||||||
MoveToNextOutput,
|
|
||||||
MoveToPreviousOutput,
|
|
||||||
SendToNextOutput,
|
|
||||||
SendToPreviousOutput,
|
|
||||||
SwitchOutput(Direction),
|
|
||||||
MoveToOutput(Direction),
|
|
||||||
SendToOutput(Direction),
|
|
||||||
|
|
||||||
MigrateWorkspaceToNextOutput,
|
|
||||||
MigrateWorkspaceToPreviousOutput,
|
|
||||||
MigrateWorkspaceToOutput(Direction),
|
|
||||||
|
|
||||||
Focus(FocusDirection),
|
|
||||||
Move(Direction),
|
|
||||||
|
|
||||||
ToggleOrientation,
|
|
||||||
Orientation(crate::shell::layout::Orientation),
|
|
||||||
|
|
||||||
ToggleStacking,
|
|
||||||
ToggleTiling,
|
|
||||||
ToggleWindowFloating,
|
|
||||||
ToggleSticky,
|
|
||||||
SwapWindow,
|
|
||||||
|
|
||||||
Resizing(ResizeDirection),
|
|
||||||
#[serde(skip)]
|
|
||||||
_ResizingInternal(ResizeDirection, ResizeEdge, KeyState),
|
|
||||||
Minimize,
|
|
||||||
Maximize,
|
|
||||||
Spawn(String),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_binding(
|
pub fn add_default_bindings(shortcuts: &mut Shortcuts, workspace_layout: WorkspaceLayout) {
|
||||||
key_bindings: &mut HashMap<KeyPattern, Action>,
|
|
||||||
modifiers: KeyModifiers,
|
|
||||||
keys: impl Iterator<Item = Keysym>,
|
|
||||||
action: Action,
|
|
||||||
) {
|
|
||||||
if !key_bindings.values().any(|a| a == &action) {
|
|
||||||
for key in keys {
|
|
||||||
let pattern = KeyPattern {
|
|
||||||
modifiers: modifiers.clone(),
|
|
||||||
key: Some(key),
|
|
||||||
};
|
|
||||||
if !key_bindings.contains_key(&pattern) {
|
|
||||||
key_bindings.insert(pattern, action.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_default_bindings(
|
|
||||||
key_bindings: &mut HashMap<KeyPattern, Action>,
|
|
||||||
workspace_layout: WorkspaceLayout,
|
|
||||||
) {
|
|
||||||
let (
|
let (
|
||||||
workspace_previous,
|
workspace_previous,
|
||||||
workspace_next,
|
workspace_next,
|
||||||
|
|
@ -223,102 +31,110 @@ pub fn add_default_bindings(
|
||||||
(output_next, output_next_dir),
|
(output_next, output_next_dir),
|
||||||
) = match workspace_layout {
|
) = match workspace_layout {
|
||||||
WorkspaceLayout::Horizontal => (
|
WorkspaceLayout::Horizontal => (
|
||||||
[Keysym::Left, Keysym::h],
|
[xkb::Keysym::Left, xkb::Keysym::h],
|
||||||
[Keysym::Right, Keysym::l],
|
[xkb::Keysym::Right, xkb::Keysym::l],
|
||||||
([Keysym::Up, Keysym::k], Direction::Up),
|
(
|
||||||
([Keysym::Down, Keysym::j], Direction::Down),
|
[xkb::Keysym::Up, xkb::Keysym::k],
|
||||||
|
shortcuts::action::Direction::Up,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[xkb::Keysym::Down, xkb::Keysym::j],
|
||||||
|
shortcuts::action::Direction::Down,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
WorkspaceLayout::Vertical => (
|
WorkspaceLayout::Vertical => (
|
||||||
[Keysym::Up, Keysym::k],
|
[xkb::Keysym::Up, xkb::Keysym::k],
|
||||||
[Keysym::Down, Keysym::j],
|
[xkb::Keysym::Down, xkb::Keysym::j],
|
||||||
([Keysym::Left, Keysym::h], Direction::Left),
|
(
|
||||||
([Keysym::Right, Keysym::l], Direction::Right),
|
[xkb::Keysym::Left, xkb::Keysym::h],
|
||||||
|
shortcuts::action::Direction::Left,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
[xkb::Keysym::Right, xkb::Keysym::l],
|
||||||
|
shortcuts::action::Direction::Right,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
insert_binding(
|
shortcuts.insert_default_binding(
|
||||||
key_bindings,
|
Modifiers::new().logo().ctrl(),
|
||||||
KeyModifiers {
|
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
workspace_previous.iter().copied(),
|
workspace_previous.iter().copied(),
|
||||||
Action::PreviousWorkspace,
|
shortcuts::Action::PreviousWorkspace,
|
||||||
);
|
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
|
||||||
KeyModifiers {
|
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
workspace_next.iter().copied(),
|
|
||||||
Action::NextWorkspace,
|
|
||||||
);
|
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
|
||||||
KeyModifiers {
|
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
shift: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
workspace_previous.iter().copied(),
|
|
||||||
Action::MoveToPreviousWorkspace,
|
|
||||||
);
|
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
|
||||||
KeyModifiers {
|
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
shift: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
workspace_next.iter().copied(),
|
|
||||||
Action::MoveToNextWorkspace,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
insert_binding(
|
shortcuts.insert_default_binding(
|
||||||
key_bindings,
|
Modifiers::new().logo().ctrl(),
|
||||||
KeyModifiers {
|
workspace_next.iter().copied(),
|
||||||
logo: true,
|
shortcuts::Action::NextWorkspace,
|
||||||
ctrl: true,
|
);
|
||||||
..Default::default()
|
|
||||||
},
|
shortcuts.insert_default_binding(
|
||||||
|
Modifiers::new().logo().ctrl().shift(),
|
||||||
|
workspace_previous.iter().copied(),
|
||||||
|
shortcuts::Action::MoveToPreviousWorkspace,
|
||||||
|
);
|
||||||
|
|
||||||
|
shortcuts.insert_default_binding(
|
||||||
|
Modifiers::new().logo().ctrl().shift(),
|
||||||
|
workspace_next.iter().copied(),
|
||||||
|
shortcuts::Action::MoveToNextWorkspace,
|
||||||
|
);
|
||||||
|
|
||||||
|
shortcuts.insert_default_binding(
|
||||||
|
Modifiers::new().logo().ctrl(),
|
||||||
output_previous.iter().copied(),
|
output_previous.iter().copied(),
|
||||||
Action::SwitchOutput(output_previous_dir),
|
shortcuts::Action::SwitchOutput(output_previous_dir),
|
||||||
);
|
);
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
shortcuts.insert_default_binding(
|
||||||
KeyModifiers {
|
Modifiers::new().logo().ctrl(),
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
output_next.iter().copied(),
|
output_next.iter().copied(),
|
||||||
Action::SwitchOutput(output_next_dir),
|
shortcuts::Action::SwitchOutput(output_next_dir),
|
||||||
);
|
);
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
shortcuts.insert_default_binding(
|
||||||
KeyModifiers {
|
Modifiers::new().logo().ctrl().shift(),
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
shift: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
output_previous.iter().copied(),
|
output_previous.iter().copied(),
|
||||||
Action::MoveToOutput(output_previous_dir),
|
shortcuts::Action::MoveToOutput(output_previous_dir),
|
||||||
);
|
);
|
||||||
insert_binding(
|
|
||||||
key_bindings,
|
shortcuts.insert_default_binding(
|
||||||
KeyModifiers {
|
Modifiers::new().logo().ctrl().shift(),
|
||||||
logo: true,
|
|
||||||
ctrl: true,
|
|
||||||
shift: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
output_next.iter().copied(),
|
output_next.iter().copied(),
|
||||||
Action::MoveToOutput(output_next_dir),
|
shortcuts::Action::MoveToOutput(output_next_dir),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convert `cosmic_settings_config::shortcuts::State` to `smithay::backend::input::KeyState`.
|
||||||
|
pub fn cosmic_keystate_to_smithay(value: KeyState) -> smithay::backend::input::KeyState {
|
||||||
|
match value {
|
||||||
|
KeyState::Pressed => smithay::backend::input::KeyState::Pressed,
|
||||||
|
KeyState::Released => smithay::backend::input::KeyState::Released,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert `smithay::backend::input::KeyState` to `cosmic_settings_config::shortcuts::State`.
|
||||||
|
pub fn cosmic_keystate_from_smithay(value: smithay::backend::input::KeyState) -> KeyState {
|
||||||
|
match value {
|
||||||
|
smithay::backend::input::KeyState::Pressed => KeyState::Pressed,
|
||||||
|
smithay::backend::input::KeyState::Released => KeyState::Released,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compare `cosmic_settings_config::shortcuts::Modifiers` to `smithay::input::keyboard::ModifiersState`.
|
||||||
|
pub fn cosmic_modifiers_eq_smithay(this: &Modifiers, other: &ModifiersState) -> bool {
|
||||||
|
this.ctrl == other.ctrl
|
||||||
|
&& this.alt == other.alt
|
||||||
|
&& this.shift == other.shift
|
||||||
|
&& this.logo == other.logo
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert `smithay::input::keyboard::ModifiersState` to `cosmic_settings_config::shortcuts::Modifiers`
|
||||||
|
pub fn cosmic_modifiers_from_smithay(value: ModifiersState) -> Modifiers {
|
||||||
|
Modifiers {
|
||||||
|
ctrl: value.ctrl,
|
||||||
|
alt: value.alt,
|
||||||
|
shift: value.shift,
|
||||||
|
logo: value.logo,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use cosmic_config::{ConfigGet, CosmicConfigEntry};
|
use cosmic_config::{ConfigGet, CosmicConfigEntry};
|
||||||
|
use cosmic_settings_config::{shortcuts, Shortcuts};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smithay::wayland::xdg_activation::XdgActivationState;
|
use smithay::wayland::xdg_activation::XdgActivationState;
|
||||||
pub use smithay::{
|
pub use smithay::{
|
||||||
|
|
@ -25,66 +26,33 @@ pub use smithay::{
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
cell::RefCell,
|
cell::RefCell,
|
||||||
collections::HashMap,
|
collections::{BTreeMap, HashMap},
|
||||||
fs::OpenOptions,
|
fs::OpenOptions,
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
sync::{atomic::AtomicBool, Arc, RwLock},
|
sync::{atomic::AtomicBool, Arc, RwLock},
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{error, warn};
|
||||||
|
|
||||||
mod input_config;
|
mod input_config;
|
||||||
mod key_bindings;
|
pub mod key_bindings;
|
||||||
pub use key_bindings::{Action, KeyModifier, KeyModifiers, KeyPattern};
|
pub use key_bindings::{Action, PrivateAction};
|
||||||
mod types;
|
mod types;
|
||||||
pub use self::types::*;
|
pub use self::types::*;
|
||||||
use cosmic_comp_config::{
|
use cosmic_comp_config::{
|
||||||
input::InputConfig,
|
input::InputConfig, workspace::WorkspaceConfig, CosmicCompConfig, TileBehavior, XkbConfig,
|
||||||
workspace::{WorkspaceConfig, WorkspaceLayout},
|
|
||||||
CosmicCompConfig, TileBehavior, XkbConfig,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub static_conf: StaticConfig,
|
|
||||||
pub dynamic_conf: DynamicConfig,
|
pub dynamic_conf: DynamicConfig,
|
||||||
pub cosmic_helper: cosmic_config::Config,
|
pub cosmic_helper: cosmic_config::Config,
|
||||||
pub cosmic_conf: CosmicCompConfig,
|
pub cosmic_conf: CosmicCompConfig,
|
||||||
}
|
/// cosmic-config context for `com.system76.CosmicSettings.Shortcuts`
|
||||||
|
pub settings_context: cosmic_config::Config,
|
||||||
#[derive(Debug, Deserialize)]
|
/// Key bindings from `com.system76.CosmicSettings.Shortcuts`
|
||||||
pub struct StaticConfig {
|
pub shortcuts: Shortcuts,
|
||||||
pub key_bindings: HashMap<key_bindings::KeyPattern, key_bindings::Action>,
|
/// System actions from `com.system76.CosmicSettings.Shortcuts`
|
||||||
pub data_control_enabled: bool,
|
pub system_actions: BTreeMap<shortcuts::action::System, String>,
|
||||||
}
|
|
||||||
|
|
||||||
impl StaticConfig {
|
|
||||||
pub fn get_shortcut_for_action(&self, action: &Action) -> Option<String> {
|
|
||||||
let possible_variants = self
|
|
||||||
.key_bindings
|
|
||||||
.iter()
|
|
||||||
.filter(|(_, a)| *a == action)
|
|
||||||
.map(|(b, _)| b)
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
|
|
||||||
possible_variants
|
|
||||||
.iter()
|
|
||||||
.find(|b| b.key.is_none()) // prefer short bindings
|
|
||||||
.or_else(|| {
|
|
||||||
possible_variants
|
|
||||||
.iter() // prefer bindings containing arrow keys
|
|
||||||
.find(|b| {
|
|
||||||
matches!(
|
|
||||||
b.key,
|
|
||||||
Some(Keysym::Down)
|
|
||||||
| Some(Keysym::Up)
|
|
||||||
| Some(Keysym::Left)
|
|
||||||
| Some(Keysym::Right)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.or_else(|| possible_variants.first()) // take the first one
|
|
||||||
.map(|binding| binding.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -185,6 +153,7 @@ impl Config {
|
||||||
.expect("Failed to add cosmic-config to the event loop");
|
.expect("Failed to add cosmic-config to the event loop");
|
||||||
let xdg = xdg::BaseDirectories::new().ok();
|
let xdg = xdg::BaseDirectories::new().ok();
|
||||||
let workspace = get_config::<WorkspaceConfig>(&config, "workspaces");
|
let workspace = get_config::<WorkspaceConfig>(&config, "workspaces");
|
||||||
|
|
||||||
let cosmic_comp_config =
|
let cosmic_comp_config =
|
||||||
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
|
CosmicCompConfig::get_entry(&config).unwrap_or_else(|(errs, c)| {
|
||||||
for err in errs {
|
for err in errs {
|
||||||
|
|
@ -192,72 +161,48 @@ impl Config {
|
||||||
}
|
}
|
||||||
c
|
c
|
||||||
});
|
});
|
||||||
Config {
|
|
||||||
static_conf: Self::load_static(xdg.as_ref(), workspace.workspace_layout),
|
|
||||||
dynamic_conf: Self::load_dynamic(xdg.as_ref()),
|
|
||||||
cosmic_conf: cosmic_comp_config,
|
|
||||||
cosmic_helper: config,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_static(
|
// Source key bindings from com.system76.CosmicSettings.Shortcuts
|
||||||
xdg: Option<&xdg::BaseDirectories>,
|
let settings_context = shortcuts::context().unwrap();
|
||||||
workspace_layout: WorkspaceLayout,
|
let system_actions = shortcuts::system_actions(&config);
|
||||||
) -> StaticConfig {
|
let mut shortcuts = shortcuts::shortcuts(&settings_context);
|
||||||
let mut locations = if let Some(base) = xdg {
|
|
||||||
vec![
|
|
||||||
base.get_config_file("cosmic-comp.ron"),
|
|
||||||
base.get_config_file("cosmic-comp/config.ron"),
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
Vec::with_capacity(3)
|
|
||||||
};
|
|
||||||
if cfg!(debug_assertions) {
|
|
||||||
if let Ok(mut cwd) = std::env::current_dir() {
|
|
||||||
cwd.push("config.ron");
|
|
||||||
locations.push(cwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
locations.push(PathBuf::from("/etc/cosmic-comp/config.ron"));
|
|
||||||
locations.push(PathBuf::from("/etc/cosmic-comp.ron"));
|
|
||||||
|
|
||||||
for path in locations {
|
// Add any missing default shortcuts recommended by the compositor.
|
||||||
debug!("Trying config location: {}", path.display());
|
key_bindings::add_default_bindings(&mut shortcuts, workspace.workspace_layout);
|
||||||
if path.exists() {
|
|
||||||
info!("Using config at {}", path.display());
|
// Listen for updates to the keybindings config.
|
||||||
let Ok(file) = OpenOptions::new().read(true).open(path) else {
|
let source = cosmic_config::calloop::ConfigWatchSource::new(&settings_context).expect(
|
||||||
error!("Failed to open config file.");
|
"failed to create config watch source for com.system76.CosmicSettings.Shortcuts",
|
||||||
continue;
|
);
|
||||||
};
|
_ = loop_handle.insert_source(source, |(config, keys), (), state| {
|
||||||
match ron::de::from_reader::<_, StaticConfig>(file) {
|
for key in keys {
|
||||||
Ok(mut config) => {
|
match key.as_str() {
|
||||||
key_bindings::add_default_bindings(
|
// Reload the keyboard shortcuts config.
|
||||||
&mut config.key_bindings,
|
"custom" | "defaults" => {
|
||||||
workspace_layout,
|
let mut shortcuts = shortcuts::shortcuts(&config);
|
||||||
);
|
let layout =
|
||||||
return config;
|
get_config::<WorkspaceConfig>(&config, "workspaces").workspace_layout;
|
||||||
|
key_bindings::add_default_bindings(&mut shortcuts, layout);
|
||||||
|
state.common.config.shortcuts = shortcuts;
|
||||||
}
|
}
|
||||||
Err(err) => {
|
|
||||||
error!("Malformed config file (skipping): {}", err);
|
"system_actions" => {
|
||||||
continue;
|
state.common.config.system_actions = shortcuts::system_actions(&config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
info!("No config found, consider installing a config file. Using default mapping.");
|
|
||||||
|
|
||||||
let mut config = ron::from_str(include_str!("../../config.ron")).unwrap_or_else(|err| {
|
|
||||||
debug!("Failed to load internal default config: {}", err);
|
|
||||||
StaticConfig {
|
|
||||||
// Small useful keybindings by default
|
|
||||||
key_bindings: HashMap::new(),
|
|
||||||
data_control_enabled: false,
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
key_bindings::add_default_bindings(&mut config.key_bindings, workspace_layout);
|
Config {
|
||||||
config
|
dynamic_conf: Self::load_dynamic(xdg.as_ref()),
|
||||||
|
cosmic_conf: cosmic_comp_config,
|
||||||
|
cosmic_helper: config,
|
||||||
|
settings_context,
|
||||||
|
shortcuts,
|
||||||
|
system_actions,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_dynamic(xdg: Option<&xdg::BaseDirectories>) -> DynamicConfig {
|
fn load_dynamic(xdg: Option<&xdg::BaseDirectories>) -> DynamicConfig {
|
||||||
|
|
@ -314,6 +259,10 @@ impl Config {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shortcut_for_action(&self, action: &shortcuts::Action) -> Option<String> {
|
||||||
|
self.shortcuts.shortcut_for_action(action)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn read_outputs(
|
pub fn read_outputs(
|
||||||
&mut self,
|
&mut self,
|
||||||
output_state: &mut OutputConfigurationState<State>,
|
output_state: &mut OutputConfigurationState<State>,
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,8 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use super::{KeyModifier, KeyModifiers};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use smithay::reexports::x11rb::NO_SYMBOL;
|
pub use smithay::{input::keyboard::XkbConfig as WlXkbConfig, utils::Transform};
|
||||||
pub use smithay::{
|
|
||||||
input::keyboard::{Keysym, XkbConfig as WlXkbConfig},
|
|
||||||
utils::Transform,
|
|
||||||
};
|
|
||||||
use tracing::warn;
|
|
||||||
use xkbcommon::xkb;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[serde(remote = "Transform")]
|
#[serde(remote = "Transform")]
|
||||||
|
|
@ -23,62 +16,3 @@ pub enum TransformDef {
|
||||||
Flipped180,
|
Flipped180,
|
||||||
Flipped270,
|
Flipped270,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(transparent)]
|
|
||||||
pub struct KeyModifiersDef(Vec<KeyModifier>);
|
|
||||||
|
|
||||||
impl From<KeyModifiersDef> for KeyModifiers {
|
|
||||||
fn from(src: KeyModifiersDef) -> Self {
|
|
||||||
src.0.into_iter().fold(
|
|
||||||
KeyModifiers {
|
|
||||||
ctrl: false,
|
|
||||||
alt: false,
|
|
||||||
shift: false,
|
|
||||||
logo: false,
|
|
||||||
},
|
|
||||||
|mut modis, modi: KeyModifier| {
|
|
||||||
modis += modi;
|
|
||||||
modis
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn deserialize_KeyModifiers<'de, D>(deserializer: D) -> Result<KeyModifiers, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
KeyModifiersDef::deserialize(deserializer).map(Into::into)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn deserialize_Keysym<'de, D>(deserializer: D) -> Result<Option<Keysym>, D::Error>
|
|
||||||
where
|
|
||||||
D: serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
use serde::de::{Error, Unexpected};
|
|
||||||
|
|
||||||
let name = String::deserialize(deserializer)?;
|
|
||||||
//let name = format!("KEY_{}", code);
|
|
||||||
match xkb::keysym_from_name(&name, xkb::KEYSYM_NO_FLAGS) {
|
|
||||||
x if x.raw() == NO_SYMBOL => {
|
|
||||||
match xkb::keysym_from_name(&name, xkb::KEYSYM_CASE_INSENSITIVE) {
|
|
||||||
x if x.raw() == NO_SYMBOL => Err(<D::Error as Error>::invalid_value(
|
|
||||||
Unexpected::Str(&name),
|
|
||||||
&"One of the keysym names of xkbcommon.h without the 'KEY_' prefix",
|
|
||||||
)),
|
|
||||||
x => {
|
|
||||||
warn!(
|
|
||||||
"Key-Binding '{}' only matched case insensitive for {:?}",
|
|
||||||
name,
|
|
||||||
xkb::keysym_get_name(x)
|
|
||||||
);
|
|
||||||
Ok(Some(x))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
x => Ok(Some(x)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
|
use cosmic_settings_config::shortcuts::action::Direction;
|
||||||
use smithay::utils::{Logical, Point};
|
use smithay::utils::{Logical, Point};
|
||||||
use std::{collections::VecDeque, time::Duration};
|
use std::{collections::VecDeque, time::Duration};
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::shell::Direction;
|
|
||||||
|
|
||||||
const HISTORY_LIMIT: Duration = Duration::from_millis(150);
|
const HISTORY_LIMIT: Duration = Duration::from_millis(150);
|
||||||
const DECELERATION_TOUCHPAD: f64 = 0.997;
|
const DECELERATION_TOUCHPAD: f64 = 0.997;
|
||||||
|
|
||||||
|
|
|
||||||
383
src/input/mod.rs
383
src/input/mod.rs
|
|
@ -1,20 +1,23 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Action, Config, KeyModifiers, KeyPattern},
|
config::{
|
||||||
|
key_bindings::{
|
||||||
|
cosmic_keystate_from_smithay, cosmic_modifiers_eq_smithay,
|
||||||
|
cosmic_modifiers_from_smithay,
|
||||||
|
},
|
||||||
|
Action, Config, PrivateAction,
|
||||||
|
},
|
||||||
input::gestures::{GestureState, SwipeAction},
|
input::gestures::{GestureState, SwipeAction},
|
||||||
shell::{
|
shell::{
|
||||||
focus::{
|
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget},
|
|
||||||
FocusDirection,
|
|
||||||
},
|
|
||||||
grabs::{ReleaseMode, ResizeEdge},
|
grabs::{ReleaseMode, ResizeEdge},
|
||||||
layout::{
|
layout::{
|
||||||
floating::ResizeGrabMarker,
|
floating::ResizeGrabMarker,
|
||||||
tiling::{SwapWindowGrab, TilingLayout},
|
tiling::{SwapWindowGrab, TilingLayout},
|
||||||
},
|
},
|
||||||
Direction, FocusResult, InvalidWorkspaceIndex, MoveResult, OverviewMode, ResizeDirection,
|
FocusResult, InvalidWorkspaceIndex, MoveResult, OverviewMode, ResizeMode, SeatExt, Trigger,
|
||||||
ResizeMode, SeatExt, Trigger, WorkspaceDelta,
|
WorkspaceDelta,
|
||||||
},
|
},
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -28,6 +31,8 @@ use crate::{
|
||||||
use calloop::{timer::Timer, RegistrationToken};
|
use calloop::{timer::Timer, RegistrationToken};
|
||||||
use cosmic_comp_config::{workspace::WorkspaceLayout, TileBehavior};
|
use cosmic_comp_config::{workspace::WorkspaceLayout, TileBehavior};
|
||||||
use cosmic_config::ConfigSet;
|
use cosmic_config::ConfigSet;
|
||||||
|
use cosmic_settings_config::shortcuts;
|
||||||
|
use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, ResizeDirection};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::{
|
backend::input::{
|
||||||
AbsolutePositionEvent, Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent,
|
AbsolutePositionEvent, Axis, AxisSource, Device, DeviceCapability, GestureBeginEvent,
|
||||||
|
|
@ -84,7 +89,7 @@ pub mod gestures;
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct SupressedKeys(RefCell<Vec<(Keycode, Option<RegistrationToken>)>>);
|
pub struct SupressedKeys(RefCell<Vec<(Keycode, Option<RegistrationToken>)>>);
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Debug)]
|
||||||
pub struct ModifiersShortcutQueue(RefCell<Option<KeyPattern>>);
|
pub struct ModifiersShortcutQueue(RefCell<Option<shortcuts::Binding>>);
|
||||||
|
|
||||||
impl SupressedKeys {
|
impl SupressedKeys {
|
||||||
fn add(&self, keysym: &KeysymHandle, token: impl Into<Option<RegistrationToken>>) {
|
fn add(&self, keysym: &KeysymHandle, token: impl Into<Option<RegistrationToken>>) {
|
||||||
|
|
@ -112,12 +117,12 @@ impl SupressedKeys {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModifiersShortcutQueue {
|
impl ModifiersShortcutQueue {
|
||||||
pub fn set(&self, binding: KeyPattern) {
|
pub fn set(&self, binding: shortcuts::Binding) {
|
||||||
let mut set = self.0.borrow_mut();
|
let mut set = self.0.borrow_mut();
|
||||||
*set = Some(binding);
|
*set = Some(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn take(&self, binding: &KeyPattern) -> bool {
|
pub fn take(&self, binding: &shortcuts::Binding) -> bool {
|
||||||
let mut set = self.0.borrow_mut();
|
let mut set = self.0.borrow_mut();
|
||||||
if set.is_some() && set.as_ref().unwrap() == binding {
|
if set.is_some() && set.as_ref().unwrap() == binding {
|
||||||
*set = None;
|
*set = None;
|
||||||
|
|
@ -308,20 +313,19 @@ impl State {
|
||||||
&& handle.raw_syms().contains(&action_pattern.key.unwrap())
|
&& handle.raw_syms().contains(&action_pattern.key.unwrap())
|
||||||
{
|
{
|
||||||
shell.set_resize_mode(None, &data.common.config, data.common.event_loop_handle.clone());
|
shell.set_resize_mode(None, &data.common.config, data.common.event_loop_handle.clone());
|
||||||
} else if action_pattern.modifiers != *modifiers {
|
} else if !cosmic_modifiers_eq_smithay(&action_pattern.modifiers, modifiers) {
|
||||||
let mut new_pattern = action_pattern.clone();
|
let mut new_pattern = action_pattern.clone();
|
||||||
new_pattern.modifiers = modifiers.clone().into();
|
new_pattern.modifiers = cosmic_modifiers_from_smithay(modifiers.clone());
|
||||||
let enabled = data
|
let enabled = data
|
||||||
.common
|
.common
|
||||||
.config
|
.config
|
||||||
.static_conf
|
.shortcuts
|
||||||
.key_bindings
|
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(move |(binding, action)| {
|
.find_map(move |(binding, action)| {
|
||||||
if binding == &new_pattern
|
if binding == &new_pattern
|
||||||
&& matches!(action, Action::Resizing(_))
|
&& matches!(action, shortcuts::Action::Resizing(_))
|
||||||
{
|
{
|
||||||
let Action::Resizing(direction) = action else { unreachable!() };
|
let shortcuts::Action::Resizing(direction) = action else { unreachable!() };
|
||||||
Some((new_pattern.clone(), *direction))
|
Some((new_pattern.clone(), *direction))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
@ -347,10 +351,11 @@ impl State {
|
||||||
if direction == ResizeDirection::Inwards {
|
if direction == ResizeDirection::Inwards {
|
||||||
edge.flip_direction();
|
edge.flip_direction();
|
||||||
}
|
}
|
||||||
let action = Action::_ResizingInternal(direction, edge, state);
|
let action = Action::Private(PrivateAction::Resizing(direction, edge.into(), cosmic_keystate_from_smithay(state)));
|
||||||
let key_pattern = KeyPattern {
|
let key_pattern = shortcuts::Binding {
|
||||||
modifiers: modifiers.clone().into(),
|
modifiers: cosmic_modifiers_from_smithay(modifiers.clone()),
|
||||||
key: Some(Keysym::new(handle.raw_code().raw())),
|
key: Some(Keysym::new(handle.raw_code().raw())),
|
||||||
|
description: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
if state == KeyState::Released {
|
if state == KeyState::Released {
|
||||||
|
|
@ -394,10 +399,11 @@ impl State {
|
||||||
seat.supressed_keys()
|
seat.supressed_keys()
|
||||||
.add(&handle, None);
|
.add(&handle, None);
|
||||||
return FilterResult::Intercept(Some((
|
return FilterResult::Intercept(Some((
|
||||||
Action::Escape,
|
Action::Private(PrivateAction::Escape),
|
||||||
KeyPattern {
|
shortcuts::Binding {
|
||||||
modifiers: KeyModifiers::default(),
|
modifiers: shortcuts::Modifiers::default(),
|
||||||
key: Some(Keysym::Escape),
|
key: Some(Keysym::Escape),
|
||||||
|
description: None,
|
||||||
}
|
}
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -432,15 +438,16 @@ impl State {
|
||||||
let mut can_clear_modifiers_shortcut = true;
|
let mut can_clear_modifiers_shortcut = true;
|
||||||
if !shortcuts_inhibited {
|
if !shortcuts_inhibited {
|
||||||
let modifiers_queue = seat.modifiers_shortcut_queue();
|
let modifiers_queue = seat.modifiers_shortcut_queue();
|
||||||
|
|
||||||
for (binding, action) in
|
for (binding, action) in
|
||||||
data.common.config.static_conf.key_bindings.iter()
|
data.common.config.shortcuts.iter()
|
||||||
{
|
{
|
||||||
let modifiers_bypass = binding.key.is_none()
|
let modifiers_bypass = binding.key.is_none()
|
||||||
&& state == KeyState::Released
|
&& state == KeyState::Released
|
||||||
&& binding.modifiers != *modifiers
|
&& !cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers)
|
||||||
&& modifiers_queue.take(binding);
|
&& modifiers_queue.take(binding);
|
||||||
|
|
||||||
if !modifiers_bypass && binding.key.is_none() && state == KeyState::Pressed && binding.modifiers == *modifiers {
|
if !modifiers_bypass && binding.key.is_none() && state == KeyState::Pressed && cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers) {
|
||||||
modifiers_queue.set(binding.clone());
|
modifiers_queue.set(binding.clone());
|
||||||
can_clear_modifiers_shortcut = false;
|
can_clear_modifiers_shortcut = false;
|
||||||
}
|
}
|
||||||
|
|
@ -449,13 +456,13 @@ impl State {
|
||||||
binding.key.is_some()
|
binding.key.is_some()
|
||||||
&& state == KeyState::Pressed
|
&& state == KeyState::Pressed
|
||||||
&& handle.raw_syms().contains(&binding.key.unwrap())
|
&& handle.raw_syms().contains(&binding.key.unwrap())
|
||||||
&& binding.modifiers == *modifiers
|
&& cosmic_modifiers_eq_smithay(&binding.modifiers, modifiers)
|
||||||
) || modifiers_bypass
|
) || modifiers_bypass
|
||||||
{
|
{
|
||||||
modifiers_queue.clear();
|
modifiers_queue.clear();
|
||||||
seat.supressed_keys().add(&handle, None);
|
seat.supressed_keys().add(&handle, None);
|
||||||
return FilterResult::Intercept(Some((
|
return FilterResult::Intercept(Some((
|
||||||
action.clone(),
|
Action::Shortcut(action.clone()),
|
||||||
binding.clone(),
|
binding.clone(),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
@ -503,7 +510,9 @@ impl State {
|
||||||
Some(constraint) if constraint.is_active() => {
|
Some(constraint) if constraint.is_active() => {
|
||||||
// Constraint does not apply if not within region
|
// Constraint does not apply if not within region
|
||||||
if !constraint.region().map_or(true, |x| {
|
if !constraint.region().map_or(true, |x| {
|
||||||
x.contains((ptr.current_location() - *surface_loc).to_i32_round())
|
x.contains(
|
||||||
|
(ptr.current_location() - *surface_loc).to_i32_round(),
|
||||||
|
)
|
||||||
}) {
|
}) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1567,43 +1576,27 @@ impl State {
|
||||||
seat: &Seat<State>,
|
seat: &Seat<State>,
|
||||||
serial: Serial,
|
serial: Serial,
|
||||||
time: u32,
|
time: u32,
|
||||||
pattern: KeyPattern,
|
pattern: shortcuts::Binding,
|
||||||
direction: Option<Direction>,
|
direction: Option<Direction>,
|
||||||
propagate: bool,
|
propagate: bool,
|
||||||
) {
|
) {
|
||||||
// TODO: Detect if started from login manager or tty, and only allow
|
// TODO: Detect if started from login manager or tty, and only allow
|
||||||
// `Terminate` if it will return to login manager.
|
// `Terminate` if it will return to login manager.
|
||||||
if self.common.shell.read().unwrap().session_lock.is_some()
|
if self.common.shell.read().unwrap().session_lock.is_some()
|
||||||
&& !matches!(action, Action::Terminate | Action::Debug)
|
&& !matches!(
|
||||||
|
action,
|
||||||
|
Action::Shortcut(shortcuts::Action::Terminate)
|
||||||
|
| Action::Shortcut(shortcuts::Action::Debug)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
match action {
|
match action {
|
||||||
Action::Terminate => {
|
Action::Shortcut(action) => self
|
||||||
self.common.should_stop = true;
|
.handle_shortcut_action(action, seat, serial, time, pattern, direction, propagate),
|
||||||
}
|
|
||||||
#[cfg(feature = "debug")]
|
Action::Private(PrivateAction::Escape) => {
|
||||||
Action::Debug => {
|
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
|
||||||
shell.debug_active = !shell.debug_active;
|
|
||||||
for mapped in shell.workspaces.spaces().flat_map(|w| w.mapped()) {
|
|
||||||
mapped.set_debug(shell.debug_active);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "debug"))]
|
|
||||||
Action::Debug => {
|
|
||||||
info!("Debug overlay not included in this build.")
|
|
||||||
}
|
|
||||||
Action::Close => {
|
|
||||||
let current_output = seat.active_output();
|
|
||||||
let shell = self.common.shell.read().unwrap();
|
|
||||||
let workspace = shell.active_space(¤t_output);
|
|
||||||
if let Some(window) = workspace.focus_stack.get(seat).last() {
|
|
||||||
window.send_close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Action::Escape => {
|
|
||||||
{
|
{
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
shell.set_overview_mode(None, self.common.event_loop_handle.clone());
|
shell.set_overview_mode(None, self.common.event_loop_handle.clone());
|
||||||
|
|
@ -1622,6 +1615,65 @@ impl State {
|
||||||
keyboard.unset_grab(self);
|
keyboard.unset_grab(self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Action::Private(PrivateAction::Resizing(direction, edge, state)) => {
|
||||||
|
if state == shortcuts::State::Pressed {
|
||||||
|
self.common
|
||||||
|
.shell
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.resize(seat, direction, edge.into());
|
||||||
|
} else {
|
||||||
|
self.common
|
||||||
|
.shell
|
||||||
|
.write()
|
||||||
|
.unwrap()
|
||||||
|
.finish_resize(direction, edge.into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_shortcut_action(
|
||||||
|
&mut self,
|
||||||
|
action: shortcuts::Action,
|
||||||
|
seat: &Seat<State>,
|
||||||
|
serial: Serial,
|
||||||
|
time: u32,
|
||||||
|
pattern: shortcuts::Binding,
|
||||||
|
direction: Option<Direction>,
|
||||||
|
propagate: bool,
|
||||||
|
) {
|
||||||
|
use shortcuts::Action;
|
||||||
|
|
||||||
|
match action {
|
||||||
|
Action::Terminate => {
|
||||||
|
self.common.should_stop = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "debug")]
|
||||||
|
Action::Debug => {
|
||||||
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
shell.debug_active = !shell.debug_active;
|
||||||
|
for mapped in shell.workspaces.spaces().flat_map(|w| w.mapped()) {
|
||||||
|
mapped.set_debug(shell.debug_active);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "debug"))]
|
||||||
|
Action::Debug => {
|
||||||
|
info!("Debug overlay not included in this build.")
|
||||||
|
}
|
||||||
|
|
||||||
|
Action::Close => {
|
||||||
|
let current_output = seat.active_output();
|
||||||
|
let shell = self.common.shell.read().unwrap();
|
||||||
|
let workspace = shell.active_space(¤t_output);
|
||||||
|
if let Some(window) = workspace.focus_stack.get(seat).last() {
|
||||||
|
window.send_close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Action::Workspace(key_num) => {
|
Action::Workspace(key_num) => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let workspace = match key_num {
|
let workspace = match key_num {
|
||||||
|
|
@ -1635,6 +1687,7 @@ impl State {
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::LastWorkspace => {
|
Action::LastWorkspace => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1646,6 +1699,7 @@ impl State {
|
||||||
&mut self.common.workspace_state.update(),
|
&mut self.common.workspace_state.update(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::NextWorkspace => {
|
Action::NextWorkspace => {
|
||||||
let next = to_next_workspace(
|
let next = to_next_workspace(
|
||||||
&mut *self.common.shell.write().unwrap(),
|
&mut *self.common.shell.write().unwrap(),
|
||||||
|
|
@ -1655,7 +1709,7 @@ impl State {
|
||||||
);
|
);
|
||||||
if next.is_err() && propagate {
|
if next.is_err() && propagate {
|
||||||
if let Some(inferred) = pattern.inferred_direction() {
|
if let Some(inferred) = pattern.inferred_direction() {
|
||||||
self.handle_action(
|
self.handle_shortcut_action(
|
||||||
Action::SwitchOutput(inferred),
|
Action::SwitchOutput(inferred),
|
||||||
seat,
|
seat,
|
||||||
serial,
|
serial,
|
||||||
|
|
@ -1667,6 +1721,7 @@ impl State {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::PreviousWorkspace => {
|
Action::PreviousWorkspace => {
|
||||||
let previous = to_previous_workspace(
|
let previous = to_previous_workspace(
|
||||||
&mut *self.common.shell.write().unwrap(),
|
&mut *self.common.shell.write().unwrap(),
|
||||||
|
|
@ -1676,7 +1731,7 @@ impl State {
|
||||||
);
|
);
|
||||||
if previous.is_err() && propagate {
|
if previous.is_err() && propagate {
|
||||||
if let Some(inferred) = pattern.inferred_direction() {
|
if let Some(inferred) = pattern.inferred_direction() {
|
||||||
self.handle_action(
|
self.handle_shortcut_action(
|
||||||
Action::SwitchOutput(inferred),
|
Action::SwitchOutput(inferred),
|
||||||
seat,
|
seat,
|
||||||
serial,
|
serial,
|
||||||
|
|
@ -1688,6 +1743,7 @@ impl State {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToWorkspace(_) | x @ Action::SendToWorkspace(_) => {
|
x @ Action::MoveToWorkspace(_) | x @ Action::SendToWorkspace(_) => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let follow = matches!(x, Action::MoveToWorkspace(_));
|
let follow = matches!(x, Action::MoveToWorkspace(_));
|
||||||
|
|
@ -1708,6 +1764,7 @@ impl State {
|
||||||
Shell::set_focus(self, Some(&target), seat, None);
|
Shell::set_focus(self, Some(&target), seat, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToLastWorkspace | x @ Action::SendToLastWorkspace => {
|
x @ Action::MoveToLastWorkspace | x @ Action::SendToLastWorkspace => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1725,6 +1782,7 @@ impl State {
|
||||||
Shell::set_focus(self, Some(&target), seat, None);
|
Shell::set_focus(self, Some(&target), seat, None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToNextWorkspace | x @ Action::SendToNextWorkspace => {
|
x @ Action::MoveToNextWorkspace | x @ Action::SendToNextWorkspace => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let res = {
|
let res = {
|
||||||
|
|
@ -1750,7 +1808,7 @@ impl State {
|
||||||
}
|
}
|
||||||
Err(_) if propagate => {
|
Err(_) if propagate => {
|
||||||
if let Some(inferred) = pattern.inferred_direction() {
|
if let Some(inferred) = pattern.inferred_direction() {
|
||||||
self.handle_action(
|
self.handle_shortcut_action(
|
||||||
if matches!(x, Action::MoveToNextWorkspace) {
|
if matches!(x, Action::MoveToNextWorkspace) {
|
||||||
Action::MoveToOutput(inferred)
|
Action::MoveToOutput(inferred)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1768,6 +1826,7 @@ impl State {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToPreviousWorkspace | x @ Action::SendToPreviousWorkspace => {
|
x @ Action::MoveToPreviousWorkspace | x @ Action::SendToPreviousWorkspace => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let res = {
|
let res = {
|
||||||
|
|
@ -1794,7 +1853,7 @@ impl State {
|
||||||
}
|
}
|
||||||
Err(_) if propagate => {
|
Err(_) if propagate => {
|
||||||
if let Some(inferred) = pattern.inferred_direction() {
|
if let Some(inferred) = pattern.inferred_direction() {
|
||||||
self.handle_action(
|
self.handle_shortcut_action(
|
||||||
if matches!(x, Action::MoveToPreviousWorkspace) {
|
if matches!(x, Action::MoveToPreviousWorkspace) {
|
||||||
Action::MoveToOutput(inferred)
|
Action::MoveToOutput(inferred)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1812,6 +1871,7 @@ impl State {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::SwitchOutput(direction) => {
|
Action::SwitchOutput(direction) => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1850,35 +1910,36 @@ impl State {
|
||||||
}
|
}
|
||||||
} else if propagate {
|
} else if propagate {
|
||||||
std::mem::drop(shell);
|
std::mem::drop(shell);
|
||||||
match (
|
|
||||||
|
let action = match (
|
||||||
direction,
|
direction,
|
||||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||||
) {
|
) {
|
||||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||||
| (Direction::Up, WorkspaceLayout::Vertical) => self.handle_action(
|
| (Direction::Up, WorkspaceLayout::Vertical) => {
|
||||||
Action::PreviousWorkspace,
|
Some(Action::PreviousWorkspace)
|
||||||
seat,
|
}
|
||||||
serial,
|
|
||||||
time,
|
|
||||||
pattern,
|
|
||||||
Some(direction),
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||||
| (Direction::Down, WorkspaceLayout::Vertical) => self.handle_action(
|
| (Direction::Down, WorkspaceLayout::Vertical) => {
|
||||||
Action::NextWorkspace,
|
Some(Action::NextWorkspace)
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(action) = action {
|
||||||
|
self.handle_shortcut_action(
|
||||||
|
action,
|
||||||
seat,
|
seat,
|
||||||
serial,
|
serial,
|
||||||
time,
|
time,
|
||||||
pattern,
|
pattern,
|
||||||
Some(direction),
|
Some(direction),
|
||||||
false,
|
false,
|
||||||
),
|
)
|
||||||
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::NextOutput => {
|
Action::NextOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1921,6 +1982,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::PreviousOutput => {
|
Action::PreviousOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -1964,6 +2026,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
action @ Action::MoveToOutput(_) | action @ Action::SendToOutput(_) => {
|
action @ Action::MoveToOutput(_) | action @ Action::SendToOutput(_) => {
|
||||||
let is_move_action = matches!(action, Action::MoveToOutput(_));
|
let is_move_action = matches!(action, Action::MoveToOutput(_));
|
||||||
let direction = match action {
|
let direction = match action {
|
||||||
|
|
@ -2008,30 +2071,33 @@ impl State {
|
||||||
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
self.common.config.cosmic_conf.workspaces.workspace_layout,
|
||||||
) {
|
) {
|
||||||
(Direction::Left, WorkspaceLayout::Horizontal)
|
(Direction::Left, WorkspaceLayout::Horizontal)
|
||||||
| (Direction::Up, WorkspaceLayout::Vertical) => self.handle_action(
|
| (Direction::Up, WorkspaceLayout::Vertical) => self
|
||||||
Action::MoveToPreviousWorkspace,
|
.handle_shortcut_action(
|
||||||
seat,
|
Action::MoveToPreviousWorkspace,
|
||||||
serial,
|
seat,
|
||||||
time,
|
serial,
|
||||||
pattern,
|
time,
|
||||||
Some(direction),
|
pattern,
|
||||||
false,
|
Some(direction),
|
||||||
),
|
false,
|
||||||
|
),
|
||||||
(Direction::Right, WorkspaceLayout::Horizontal)
|
(Direction::Right, WorkspaceLayout::Horizontal)
|
||||||
| (Direction::Down, WorkspaceLayout::Vertical) => self.handle_action(
|
| (Direction::Down, WorkspaceLayout::Vertical) => self
|
||||||
Action::MoveToNextWorkspace,
|
.handle_shortcut_action(
|
||||||
seat,
|
Action::MoveToNextWorkspace,
|
||||||
serial,
|
seat,
|
||||||
time,
|
serial,
|
||||||
pattern,
|
time,
|
||||||
Some(direction),
|
pattern,
|
||||||
false,
|
Some(direction),
|
||||||
),
|
false,
|
||||||
|
),
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToNextOutput | x @ Action::SendToNextOutput => {
|
x @ Action::MoveToNextOutput | x @ Action::SendToNextOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2069,6 +2135,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
x @ Action::MoveToPreviousOutput | x @ Action::SendToPreviousOutput => {
|
x @ Action::MoveToPreviousOutput | x @ Action::SendToPreviousOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2107,6 +2174,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::MigrateWorkspaceToNextOutput => {
|
Action::MigrateWorkspaceToNextOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let (active, next_output) = {
|
let (active, next_output) = {
|
||||||
|
|
@ -2125,6 +2193,7 @@ impl State {
|
||||||
.migrate_workspace(¤t_output, &next_output, &active);
|
.migrate_workspace(¤t_output, &next_output, &active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::MigrateWorkspaceToPreviousOutput => {
|
Action::MigrateWorkspaceToPreviousOutput => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let (active, prev_output) = {
|
let (active, prev_output) = {
|
||||||
|
|
@ -2144,6 +2213,7 @@ impl State {
|
||||||
.migrate_workspace(¤t_output, &prev_output, &active);
|
.migrate_workspace(¤t_output, &prev_output, &active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::MigrateWorkspaceToOutput(direction) => {
|
Action::MigrateWorkspaceToOutput(direction) => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let (active, next_output) = {
|
let (active, next_output) = {
|
||||||
|
|
@ -2160,6 +2230,7 @@ impl State {
|
||||||
.migrate_workspace(¤t_output, &next_output, &active);
|
.migrate_workspace(¤t_output, &next_output, &active);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Focus(focus) => {
|
Action::Focus(focus) => {
|
||||||
let result = self.common.shell.read().unwrap().next_focus(focus, seat);
|
let result = self.common.shell.read().unwrap().next_focus(focus, seat);
|
||||||
|
|
||||||
|
|
@ -2174,7 +2245,7 @@ impl State {
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(direction) = dir {
|
if let Some(direction) = dir {
|
||||||
self.handle_action(
|
self.handle_shortcut_action(
|
||||||
Action::SwitchOutput(direction),
|
Action::SwitchOutput(direction),
|
||||||
seat,
|
seat,
|
||||||
serial,
|
serial,
|
||||||
|
|
@ -2191,6 +2262,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Move(direction) => {
|
Action::Move(direction) => {
|
||||||
let res = self
|
let res = self
|
||||||
.common
|
.common
|
||||||
|
|
@ -2199,7 +2271,7 @@ impl State {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.move_current_element(direction, seat);
|
.move_current_element(direction, seat);
|
||||||
match res {
|
match res {
|
||||||
MoveResult::MoveFurther(_move_further) => self.handle_action(
|
MoveResult::MoveFurther(_move_further) => self.handle_shortcut_action(
|
||||||
Action::MoveToOutput(direction),
|
Action::MoveToOutput(direction),
|
||||||
seat,
|
seat,
|
||||||
serial,
|
serial,
|
||||||
|
|
@ -2226,6 +2298,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::SwapWindow => {
|
Action::SwapWindow => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2249,6 +2322,7 @@ impl State {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Minimize => {
|
Action::Minimize => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2259,6 +2333,7 @@ impl State {
|
||||||
shell.minimize_request(&window);
|
shell.minimize_request(&window);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Maximize => {
|
Action::Maximize => {
|
||||||
let current_output = seat.active_output();
|
let current_output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2269,32 +2344,20 @@ impl State {
|
||||||
shell.maximize_toggle(&window, seat);
|
shell.maximize_toggle(&window, seat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Resizing(direction) => self.common.shell.write().unwrap().set_resize_mode(
|
Action::Resizing(direction) => self.common.shell.write().unwrap().set_resize_mode(
|
||||||
Some((pattern, direction)),
|
Some((pattern, direction)),
|
||||||
&self.common.config,
|
&self.common.config,
|
||||||
self.common.event_loop_handle.clone(),
|
self.common.event_loop_handle.clone(),
|
||||||
),
|
),
|
||||||
Action::_ResizingInternal(direction, edge, state) => {
|
|
||||||
if state == KeyState::Pressed {
|
|
||||||
self.common
|
|
||||||
.shell
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.resize(seat, direction, edge);
|
|
||||||
} else {
|
|
||||||
self.common
|
|
||||||
.shell
|
|
||||||
.write()
|
|
||||||
.unwrap()
|
|
||||||
.finish_resize(direction, edge);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Action::ToggleOrientation => {
|
Action::ToggleOrientation => {
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
let workspace = shell.active_space_mut(&output);
|
let workspace = shell.active_space_mut(&output);
|
||||||
workspace.tiling_layer.update_orientation(None, &seat);
|
workspace.tiling_layer.update_orientation(None, &seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::Orientation(orientation) => {
|
Action::Orientation(orientation) => {
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
@ -2303,6 +2366,7 @@ impl State {
|
||||||
.tiling_layer
|
.tiling_layer
|
||||||
.update_orientation(Some(orientation), &seat);
|
.update_orientation(Some(orientation), &seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::ToggleStacking => {
|
Action::ToggleStacking => {
|
||||||
let res = self
|
let res = self
|
||||||
.common
|
.common
|
||||||
|
|
@ -2314,6 +2378,7 @@ impl State {
|
||||||
Shell::set_focus(self, Some(&new_focus), seat, Some(serial));
|
Shell::set_focus(self, Some(&new_focus), seat, Some(serial));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::ToggleTiling => {
|
Action::ToggleTiling => {
|
||||||
if matches!(
|
if matches!(
|
||||||
self.common.config.cosmic_conf.autotile_behavior,
|
self.common.config.cosmic_conf.autotile_behavior,
|
||||||
|
|
@ -2345,12 +2410,14 @@ impl State {
|
||||||
workspace.toggle_tiling(seat, &mut guard);
|
workspace.toggle_tiling(seat, &mut guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::ToggleWindowFloating => {
|
Action::ToggleWindowFloating => {
|
||||||
let output = seat.active_output();
|
let output = seat.active_output();
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
let workspace = shell.active_space_mut(&output);
|
let workspace = shell.active_space_mut(&output);
|
||||||
workspace.toggle_floating_window_focused(seat);
|
workspace.toggle_floating_window_focused(seat);
|
||||||
}
|
}
|
||||||
|
|
||||||
Action::ToggleSticky => {
|
Action::ToggleSticky => {
|
||||||
self.common
|
self.common
|
||||||
.shell
|
.shell
|
||||||
|
|
@ -2358,51 +2425,64 @@ impl State {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.toggle_sticky_current(seat);
|
.toggle_sticky_current(seat);
|
||||||
}
|
}
|
||||||
Action::Spawn(command) => {
|
|
||||||
let mut shell = self.common.shell.write().unwrap();
|
|
||||||
|
|
||||||
let (token, data) = self.common.xdg_activation_state.create_external_token(None);
|
// Gets the configured command for a given system action.
|
||||||
let (token, data) = (token.clone(), data.clone());
|
Action::System(system) => {
|
||||||
|
if let Some(command) = self.common.config.system_actions.get(&system) {
|
||||||
let output = shell.seats.last_active().active_output();
|
self.spawn_command(command.clone());
|
||||||
let workspace = shell.active_space_mut(&output);
|
}
|
||||||
workspace.pending_tokens.insert(token.clone());
|
|
||||||
let handle = workspace.handle;
|
|
||||||
std::mem::drop(shell);
|
|
||||||
data.user_data
|
|
||||||
.insert_if_missing(move || ActivationContext::Workspace(handle));
|
|
||||||
|
|
||||||
let wayland_display = self.common.socket.clone();
|
|
||||||
let display = self
|
|
||||||
.common
|
|
||||||
.xwayland_state
|
|
||||||
.as_ref()
|
|
||||||
.map(|s| format!(":{}", s.display))
|
|
||||||
.unwrap_or_default();
|
|
||||||
|
|
||||||
let mut cmd = std::process::Command::new("/bin/sh");
|
|
||||||
|
|
||||||
cmd.arg("-c")
|
|
||||||
.arg(command.clone())
|
|
||||||
.env("WAYLAND_DISPLAY", &wayland_display)
|
|
||||||
.env("DISPLAY", &display)
|
|
||||||
.env("XDG_ACTIVATION_TOKEN", &*token)
|
|
||||||
.env("DESKTOP_STARTUP_ID", &*token)
|
|
||||||
.env_remove("COSMIC_SESSION_SOCK");
|
|
||||||
unsafe { cmd.pre_exec(|| Ok(crate::utils::rlimit::restore_nofile_limit())) };
|
|
||||||
|
|
||||||
std::thread::spawn(move || match cmd.spawn() {
|
|
||||||
Ok(mut child) => {
|
|
||||||
let _res = child.wait();
|
|
||||||
}
|
|
||||||
Err(err) => {
|
|
||||||
tracing::warn!(?err, "Failed to spawn \"{}\"", command);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Action::Spawn(command) => self.spawn_command(command),
|
||||||
|
|
||||||
|
// Do nothing
|
||||||
|
Action::Disable => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spawn_command(&mut self, command: String) {
|
||||||
|
let mut shell = self.common.shell.write().unwrap();
|
||||||
|
|
||||||
|
let (token, data) = self.common.xdg_activation_state.create_external_token(None);
|
||||||
|
let (token, data) = (token.clone(), data.clone());
|
||||||
|
|
||||||
|
let output = shell.seats.last_active().active_output();
|
||||||
|
let workspace = shell.active_space_mut(&output);
|
||||||
|
workspace.pending_tokens.insert(token.clone());
|
||||||
|
let handle = workspace.handle;
|
||||||
|
std::mem::drop(shell);
|
||||||
|
data.user_data
|
||||||
|
.insert_if_missing(move || ActivationContext::Workspace(handle));
|
||||||
|
|
||||||
|
let wayland_display = self.common.socket.clone();
|
||||||
|
let display = self
|
||||||
|
.common
|
||||||
|
.xwayland_state
|
||||||
|
.as_ref()
|
||||||
|
.map(|s| format!(":{}", s.display))
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let mut cmd = std::process::Command::new("/bin/sh");
|
||||||
|
|
||||||
|
cmd.arg("-c")
|
||||||
|
.arg(&command)
|
||||||
|
.env("WAYLAND_DISPLAY", &wayland_display)
|
||||||
|
.env("DISPLAY", &display)
|
||||||
|
.env("XDG_ACTIVATION_TOKEN", &*token)
|
||||||
|
.env("DESKTOP_STARTUP_ID", &*token)
|
||||||
|
.env_remove("COSMIC_SESSION_SOCK");
|
||||||
|
unsafe { cmd.pre_exec(|| Ok(crate::utils::rlimit::restore_nofile_limit())) };
|
||||||
|
|
||||||
|
std::thread::spawn(move || match cmd.spawn() {
|
||||||
|
Ok(mut child) => {
|
||||||
|
let _res = child.wait();
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
tracing::warn!(?err, "Failed to spawn \"{}\"", command);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Try to get rid of the *mutable* Shell references (needed for hovered_stack in floating_layout)
|
// TODO: Try to get rid of the *mutable* Shell references (needed for hovered_stack in floating_layout)
|
||||||
pub fn surface_under(
|
pub fn surface_under(
|
||||||
global_pos: Point<f64, Global>,
|
global_pos: Point<f64, Global>,
|
||||||
|
|
@ -2463,8 +2543,11 @@ impl State {
|
||||||
geo,
|
geo,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
PointerFocusTarget::under_surface(window, relative_pos.as_logical())
|
PointerFocusTarget::under_surface(window, relative_pos.as_logical()).map(
|
||||||
.map(|(target, surface_loc)| (target, (output_geo.loc + surface_loc.as_global()).to_f64()))
|
|(target, surface_loc)| {
|
||||||
|
(target, (output_geo.loc + surface_loc.as_global()).to_f64())
|
||||||
|
},
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
{
|
{
|
||||||
let layers = layer_map_for_output(output);
|
let layers = layer_map_for_output(output);
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,14 @@ use smithay::desktop::WindowSurface;
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
focus::{target::PointerFocusTarget, FocusDirection},
|
focus::target::PointerFocusTarget,
|
||||||
layout::{
|
layout::{
|
||||||
floating::{ResizeState, TiledCorners},
|
floating::{ResizeState, TiledCorners},
|
||||||
tiling::NodeDesc,
|
tiling::NodeDesc,
|
||||||
},
|
},
|
||||||
Direction, ManagedLayer, SeatExt,
|
ManagedLayer, SeatExt,
|
||||||
};
|
};
|
||||||
|
use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection};
|
||||||
|
|
||||||
space_elements! {
|
space_elements! {
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
use std::sync::Mutex;
|
use std::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Action, Config},
|
config::Config,
|
||||||
fl,
|
fl,
|
||||||
shell::{grabs::ResizeEdge, ResizeDirection},
|
shell::grabs::ResizeEdge,
|
||||||
utils::iced::{IcedElement, Program},
|
utils::iced::{IcedElement, Program},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -15,6 +15,7 @@ use cosmic::{
|
||||||
widget::{icon::from_name, text},
|
widget::{icon::from_name, text},
|
||||||
Apply,
|
Apply,
|
||||||
};
|
};
|
||||||
|
use cosmic_settings_config::shortcuts::action::{Action, ResizeDirection};
|
||||||
use smithay::utils::Size;
|
use smithay::utils::Size;
|
||||||
|
|
||||||
pub type ResizeIndicator = IcedElement<ResizeIndicatorInternal>;
|
pub type ResizeIndicator = IcedElement<ResizeIndicatorInternal>;
|
||||||
|
|
@ -30,8 +31,7 @@ pub fn resize_indicator(
|
||||||
edges: Mutex::new(ResizeEdge::all()),
|
edges: Mutex::new(ResizeEdge::all()),
|
||||||
direction,
|
direction,
|
||||||
shortcut1: config
|
shortcut1: config
|
||||||
.static_conf
|
.shortcuts
|
||||||
.key_bindings
|
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(pattern, action)| {
|
.find_map(|(pattern, action)| {
|
||||||
(*action == Action::Resizing(ResizeDirection::Outwards)).then_some(pattern)
|
(*action == Action::Resizing(ResizeDirection::Outwards)).then_some(pattern)
|
||||||
|
|
@ -39,8 +39,7 @@ pub fn resize_indicator(
|
||||||
.map(|pattern| format!("{}: ", pattern.to_string()))
|
.map(|pattern| format!("{}: ", pattern.to_string()))
|
||||||
.unwrap_or_else(|| crate::fl!("unknown-keybinding")),
|
.unwrap_or_else(|| crate::fl!("unknown-keybinding")),
|
||||||
shortcut2: config
|
shortcut2: config
|
||||||
.static_conf
|
.shortcuts
|
||||||
.key_bindings
|
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(pattern, action)| {
|
.find_map(|(pattern, action)| {
|
||||||
(*action == Action::Resizing(ResizeDirection::Inwards)).then_some(pattern)
|
(*action == Action::Resizing(ResizeDirection::Inwards)).then_some(pattern)
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,9 @@ use super::{surface::RESIZE_BORDER, window::Focus, CosmicSurface};
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::cursor::{CursorShape, CursorState},
|
backend::render::cursor::{CursorShape, CursorState},
|
||||||
shell::{
|
shell::{
|
||||||
focus::{target::PointerFocusTarget, FocusDirection},
|
focus::target::PointerFocusTarget,
|
||||||
grabs::{ReleaseMode, ResizeEdge},
|
grabs::{ReleaseMode, ResizeEdge},
|
||||||
layout::tiling::NodeDesc,
|
layout::tiling::NodeDesc,
|
||||||
Direction,
|
|
||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
utils::{
|
utils::{
|
||||||
|
|
@ -21,7 +20,9 @@ use cosmic::{
|
||||||
iced_widget::scrollable::AbsoluteOffset,
|
iced_widget::scrollable::AbsoluteOffset,
|
||||||
theme, widget as cosmic_widget, Apply, Element as CosmicElement,
|
theme, widget as cosmic_widget, Apply, Element as CosmicElement,
|
||||||
};
|
};
|
||||||
|
use cosmic_settings_config::shortcuts;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
use shortcuts::action::{Direction, FocusDirection};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{
|
backend::{
|
||||||
input::KeyState,
|
input::KeyState,
|
||||||
|
|
|
||||||
|
|
@ -27,16 +27,6 @@ use super::{layout::floating::FloatingLayout, SeatExt};
|
||||||
|
|
||||||
pub mod target;
|
pub mod target;
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum FocusDirection {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
In,
|
|
||||||
Out,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct FocusStack<'a>(pub(super) Option<&'a IndexSet<CosmicMapped>>);
|
pub struct FocusStack<'a>(pub(super) Option<&'a IndexSet<CosmicMapped>>);
|
||||||
pub struct FocusStackMut<'a>(pub(super) &'a mut IndexSet<CosmicMapped>);
|
pub struct FocusStackMut<'a>(pub(super) &'a mut IndexSet<CosmicMapped>);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
use cosmic_settings_config::shortcuts::Action;
|
||||||
use smithay::{input::pointer::MotionEvent, utils::SERIAL_COUNTER, wayland::seat::WaylandFocus};
|
use smithay::{input::pointer::MotionEvent, utils::SERIAL_COUNTER, wayland::seat::WaylandFocus};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Action, StaticConfig},
|
config::Config,
|
||||||
fl,
|
fl,
|
||||||
shell::{
|
shell::{
|
||||||
element::{CosmicMapped, CosmicWindow},
|
element::{CosmicMapped, CosmicWindow},
|
||||||
|
|
@ -93,7 +94,7 @@ pub fn tab_items(
|
||||||
stack: &CosmicMapped,
|
stack: &CosmicMapped,
|
||||||
tab: &CosmicSurface,
|
tab: &CosmicSurface,
|
||||||
is_tiled: bool,
|
is_tiled: bool,
|
||||||
config: &StaticConfig,
|
config: &Config,
|
||||||
) -> impl Iterator<Item = Item> {
|
) -> impl Iterator<Item = Item> {
|
||||||
let unstack_clone_stack = stack.clone();
|
let unstack_clone_stack = stack.clone();
|
||||||
let unstack_clone_tab = tab.clone();
|
let unstack_clone_tab = tab.clone();
|
||||||
|
|
@ -145,7 +146,7 @@ pub fn tab_items(
|
||||||
Item::new(fl!("window-menu-close"), move |_handle| {
|
Item::new(fl!("window-menu-close"), move |_handle| {
|
||||||
close_clone.close();
|
close_clone.close();
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::Close)),
|
.shortcut(config.shortcut_for_action(&Action::Close)),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
}
|
}
|
||||||
|
|
@ -157,7 +158,7 @@ pub fn window_items(
|
||||||
is_sticky: bool,
|
is_sticky: bool,
|
||||||
tiling_enabled: bool,
|
tiling_enabled: bool,
|
||||||
possible_resizes: ResizeEdge,
|
possible_resizes: ResizeEdge,
|
||||||
config: &StaticConfig,
|
config: &Config,
|
||||||
) -> impl Iterator<Item = Item> {
|
) -> impl Iterator<Item = Item> {
|
||||||
let minimize_clone = window.clone();
|
let minimize_clone = window.clone();
|
||||||
let maximize_clone = window.clone();
|
let maximize_clone = window.clone();
|
||||||
|
|
@ -181,7 +182,7 @@ pub fn window_items(
|
||||||
let mapped = stack_clone.clone();
|
let mapped = stack_clone.clone();
|
||||||
let _ = handle.insert_idle(move |state| toggle_stacking(state, &mapped));
|
let _ = handle.insert_idle(move |state| toggle_stacking(state, &mapped));
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::ToggleStacking)),
|
.shortcut(config.shortcut_for_action(&Action::ToggleStacking)),
|
||||||
),
|
),
|
||||||
is_stacked.then_some(
|
is_stacked.then_some(
|
||||||
Item::new(fl!("window-menu-unstack-all"), move |handle| {
|
Item::new(fl!("window-menu-unstack-all"), move |handle| {
|
||||||
|
|
@ -190,7 +191,7 @@ pub fn window_items(
|
||||||
toggle_stacking(state, &mapped);
|
toggle_stacking(state, &mapped);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::ToggleStacking)),
|
.shortcut(config.shortcut_for_action(&Action::ToggleStacking)),
|
||||||
),
|
),
|
||||||
Some(Item::Separator),
|
Some(Item::Separator),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -205,7 +206,7 @@ pub fn window_items(
|
||||||
.minimize_request(&mapped);
|
.minimize_request(&mapped);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::Minimize)),
|
.shortcut(config.shortcut_for_action(&Action::Minimize)),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
Item::new(fl!("window-menu-maximize"), move |handle| {
|
Item::new(fl!("window-menu-maximize"), move |handle| {
|
||||||
|
|
@ -216,7 +217,7 @@ pub fn window_items(
|
||||||
shell.maximize_toggle(&mapped, &seat);
|
shell.maximize_toggle(&mapped, &seat);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::Maximize))
|
.shortcut(config.shortcut_for_action(&Action::Maximize))
|
||||||
.toggled(window.is_maximized(false)),
|
.toggled(window.is_maximized(false)),
|
||||||
),
|
),
|
||||||
(tiling_enabled && !is_sticky).then_some(
|
(tiling_enabled && !is_sticky).then_some(
|
||||||
|
|
@ -230,7 +231,7 @@ pub fn window_items(
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::ToggleWindowFloating))
|
.shortcut(config.shortcut_for_action(&Action::ToggleWindowFloating))
|
||||||
.toggled(!is_tiled),
|
.toggled(!is_tiled),
|
||||||
),
|
),
|
||||||
Some(Item::Separator),
|
Some(Item::Separator),
|
||||||
|
|
@ -410,7 +411,7 @@ pub fn window_items(
|
||||||
let mapped = move_prev_clone.clone();
|
let mapped = move_prev_clone.clone();
|
||||||
let _ = handle.insert_idle(move |state| move_prev_workspace(state, &mapped));
|
let _ = handle.insert_idle(move |state| move_prev_workspace(state, &mapped));
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::MoveToPreviousWorkspace))
|
.shortcut(config.shortcut_for_action(&Action::MoveToPreviousWorkspace))
|
||||||
.disabled(is_sticky),
|
.disabled(is_sticky),
|
||||||
),
|
),
|
||||||
Some(
|
Some(
|
||||||
|
|
@ -418,7 +419,7 @@ pub fn window_items(
|
||||||
let mapped = move_next_clone.clone();
|
let mapped = move_next_clone.clone();
|
||||||
let _ = handle.insert_idle(move |state| move_next_workspace(state, &mapped));
|
let _ = handle.insert_idle(move |state| move_next_workspace(state, &mapped));
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::MoveToNextWorkspace))
|
.shortcut(config.shortcut_for_action(&Action::MoveToNextWorkspace))
|
||||||
.disabled(is_sticky),
|
.disabled(is_sticky),
|
||||||
),
|
),
|
||||||
Some(Item::Separator),
|
Some(Item::Separator),
|
||||||
|
|
@ -445,7 +446,7 @@ pub fn window_items(
|
||||||
Item::new(fl!("window-menu-close"), move |_handle| {
|
Item::new(fl!("window-menu-close"), move |_handle| {
|
||||||
close_clone.send_close();
|
close_clone.send_close();
|
||||||
})
|
})
|
||||||
.shortcut(config.get_shortcut_for_action(&Action::Close)),
|
.shortcut(config.shortcut_for_action(&Action::Close)),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use cosmic_settings_config::shortcuts;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
input::{
|
input::{
|
||||||
pointer::{
|
pointer::{
|
||||||
|
|
@ -106,6 +107,36 @@ impl ResizeEdge {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<shortcuts::action::ResizeEdge> for ResizeEdge {
|
||||||
|
fn from(edge: shortcuts::action::ResizeEdge) -> Self {
|
||||||
|
match edge {
|
||||||
|
shortcuts::action::ResizeEdge::Bottom => ResizeEdge::BOTTOM,
|
||||||
|
shortcuts::action::ResizeEdge::BottomLeft => ResizeEdge::BOTTOM_LEFT,
|
||||||
|
shortcuts::action::ResizeEdge::BottomRight => ResizeEdge::BOTTOM_RIGHT,
|
||||||
|
shortcuts::action::ResizeEdge::Left => ResizeEdge::LEFT,
|
||||||
|
shortcuts::action::ResizeEdge::Right => ResizeEdge::RIGHT,
|
||||||
|
shortcuts::action::ResizeEdge::Top => ResizeEdge::TOP,
|
||||||
|
shortcuts::action::ResizeEdge::TopLeft => ResizeEdge::TOP_LEFT,
|
||||||
|
shortcuts::action::ResizeEdge::TopRight => ResizeEdge::TOP_RIGHT,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<shortcuts::action::ResizeEdge> for ResizeEdge {
|
||||||
|
fn into(self) -> shortcuts::action::ResizeEdge {
|
||||||
|
match self {
|
||||||
|
ResizeEdge::BOTTOM => shortcuts::action::ResizeEdge::Bottom,
|
||||||
|
ResizeEdge::BOTTOM_LEFT => shortcuts::action::ResizeEdge::BottomLeft,
|
||||||
|
ResizeEdge::BOTTOM_RIGHT => shortcuts::action::ResizeEdge::BottomRight,
|
||||||
|
ResizeEdge::LEFT => shortcuts::action::ResizeEdge::Left,
|
||||||
|
ResizeEdge::RIGHT => shortcuts::action::ResizeEdge::Right,
|
||||||
|
ResizeEdge::TOP => shortcuts::action::ResizeEdge::Top,
|
||||||
|
ResizeEdge::TOP_LEFT => shortcuts::action::ResizeEdge::TopLeft,
|
||||||
|
_ => shortcuts::action::ResizeEdge::TopRight,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<xdg_toplevel::ResizeEdge> for ResizeEdge {
|
impl From<xdg_toplevel::ResizeEdge> for ResizeEdge {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from(x: xdg_toplevel::ResizeEdge) -> Self {
|
fn from(x: xdg_toplevel::ResizeEdge) -> Self {
|
||||||
|
|
|
||||||
|
|
@ -863,7 +863,8 @@ impl Drop for MoveGrab {
|
||||||
state,
|
state,
|
||||||
Some((
|
Some((
|
||||||
target,
|
target,
|
||||||
position.as_logical().to_f64() - window.geometry().loc.to_f64() + offset,
|
position.as_logical().to_f64() - window.geometry().loc.to_f64()
|
||||||
|
+ offset,
|
||||||
)),
|
)),
|
||||||
&MotionEvent {
|
&MotionEvent {
|
||||||
location: pointer.current_location(),
|
location: pointer.current_location(),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use std::{
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use cosmic_settings_config::shortcuts::action::ResizeDirection;
|
||||||
use keyframe::{ease, functions::EaseInOutCubic};
|
use keyframe::{ease, functions::EaseInOutCubic};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::renderer::{
|
backend::renderer::{
|
||||||
|
|
@ -36,7 +37,7 @@ use crate::{
|
||||||
FocusStackMut,
|
FocusStackMut,
|
||||||
},
|
},
|
||||||
grabs::{GrabStartData, ReleaseMode, ResizeEdge},
|
grabs::{GrabStartData, ReleaseMode, ResizeEdge},
|
||||||
CosmicSurface, Direction, ManagedLayer, MoveResult, ResizeDirection, ResizeMode,
|
CosmicSurface, Direction, ManagedLayer, MoveResult, ResizeMode,
|
||||||
},
|
},
|
||||||
state::State,
|
state::State,
|
||||||
utils::{prelude::*, tween::EaseRectangle},
|
utils::{prelude::*, tween::EaseRectangle},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: GPL-3.0-only
|
// SPDX-License-Identifier: GPL-3.0-only
|
||||||
|
|
||||||
|
use cosmic_settings_config::shortcuts::action::Orientation;
|
||||||
use regex::RegexSet;
|
use regex::RegexSet;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
desktop::WindowSurface,
|
desktop::WindowSurface,
|
||||||
|
|
@ -12,22 +13,6 @@ use super::CosmicSurface;
|
||||||
pub mod floating;
|
pub mod floating;
|
||||||
pub mod tiling;
|
pub mod tiling;
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
|
||||||
pub enum Orientation {
|
|
||||||
Horizontal,
|
|
||||||
Vertical,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Not for Orientation {
|
|
||||||
type Output = Self;
|
|
||||||
fn not(self) -> Self::Output {
|
|
||||||
match self {
|
|
||||||
Orientation::Horizontal => Orientation::Vertical,
|
|
||||||
Orientation::Vertical => Orientation::Horizontal,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref EXCEPTIONS_APPID: RegexSet = RegexSet::new(&[
|
static ref EXCEPTIONS_APPID: RegexSet = RegexSet::new(&[
|
||||||
r"Authy Desktop",
|
r"Authy Desktop",
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
use cosmic_settings_config::shortcuts;
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::input::KeyState,
|
backend::input::KeyState,
|
||||||
input::{
|
input::{
|
||||||
|
|
@ -12,7 +13,7 @@ use smithay::{
|
||||||
use xkbcommon::xkb::Keysym;
|
use xkbcommon::xkb::Keysym;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{Action, KeyPattern},
|
config::key_bindings::cosmic_modifiers_from_smithay,
|
||||||
shell::{layout::tiling::NodeDesc, OverviewMode, Trigger},
|
shell::{layout::tiling::NodeDesc, OverviewMode, Trigger},
|
||||||
state::State,
|
state::State,
|
||||||
};
|
};
|
||||||
|
|
@ -53,12 +54,11 @@ impl KeyboardGrab<State> for SwapWindowGrab {
|
||||||
let focus_bindings = &data
|
let focus_bindings = &data
|
||||||
.common
|
.common
|
||||||
.config
|
.config
|
||||||
.static_conf
|
.shortcuts
|
||||||
.key_bindings
|
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, action)| matches!(action, Action::Focus(_)))
|
.filter(|(_, action)| matches!(action, shortcuts::Action::Focus(_)))
|
||||||
.map(|(pattern, action)| {
|
.map(|(pattern, action)| {
|
||||||
let Action::Focus(direction) = action else {
|
let shortcuts::Action::Focus(direction) = action else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
(pattern.key, *direction)
|
(pattern.key, *direction)
|
||||||
|
|
@ -72,14 +72,17 @@ impl KeyboardGrab<State> for SwapWindowGrab {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
data.handle_action(
|
data.handle_shortcut_action(
|
||||||
Action::Focus(direction),
|
shortcuts::Action::Focus(direction),
|
||||||
&self.seat,
|
&self.seat,
|
||||||
serial,
|
serial,
|
||||||
time,
|
time,
|
||||||
KeyPattern {
|
shortcuts::Binding {
|
||||||
modifiers: modifiers.map(Into::into).unwrap_or_default(),
|
modifiers: modifiers
|
||||||
|
.map(cosmic_modifiers_from_smithay)
|
||||||
|
.unwrap_or_default(),
|
||||||
key: Some(Keysym::new(keycode)),
|
key: Some(Keysym::new(keycode)),
|
||||||
|
description: None,
|
||||||
},
|
},
|
||||||
None,
|
None,
|
||||||
true,
|
true,
|
||||||
|
|
|
||||||
|
|
@ -18,12 +18,12 @@ use crate::{
|
||||||
},
|
},
|
||||||
focus::{
|
focus::{
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
target::{KeyboardFocusTarget, PointerFocusTarget, WindowGroup},
|
||||||
FocusDirection, FocusStackMut,
|
FocusStackMut,
|
||||||
},
|
},
|
||||||
grabs::ResizeEdge,
|
grabs::ResizeEdge,
|
||||||
layout::Orientation,
|
layout::Orientation,
|
||||||
CosmicSurface, Direction, FocusResult, MoveResult, OutputNotMapped, OverviewMode,
|
CosmicSurface, Direction, FocusResult, MoveResult, OutputNotMapped, OverviewMode,
|
||||||
ResizeDirection, ResizeMode, Trigger,
|
ResizeMode, Trigger,
|
||||||
},
|
},
|
||||||
utils::{prelude::*, tween::EaseRectangle},
|
utils::{prelude::*, tween::EaseRectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
|
|
@ -38,6 +38,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use cosmic_settings_config::shortcuts::action::{FocusDirection, ResizeDirection};
|
||||||
use id_tree::{InsertBehavior, MoveBehavior, Node, NodeId, NodeIdError, RemoveBehavior, Tree};
|
use id_tree::{InsertBehavior, MoveBehavior, Node, NodeId, NodeIdError, RemoveBehavior, Tree};
|
||||||
use keyframe::{
|
use keyframe::{
|
||||||
ease,
|
ease,
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ use cosmic_comp_config::{
|
||||||
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{
|
use cosmic_protocols::workspace::v1::server::zcosmic_workspace_handle_v1::{
|
||||||
State as WState, TilingState,
|
State as WState, TilingState,
|
||||||
};
|
};
|
||||||
|
use cosmic_settings_config::shortcuts;
|
||||||
|
use cosmic_settings_config::shortcuts::action::{Direction, FocusDirection, ResizeDirection};
|
||||||
use keyframe::{ease, functions::EaseInOutCubic};
|
use keyframe::{ease, functions::EaseInOutCubic};
|
||||||
use smithay::{
|
use smithay::{
|
||||||
backend::{input::TouchSlot, renderer::element::RenderElementStates},
|
backend::{input::TouchSlot, renderer::element::RenderElementStates},
|
||||||
|
|
@ -49,7 +51,7 @@ use smithay::{
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::render::animations::spring::{Spring, SpringParams},
|
backend::render::animations::spring::{Spring, SpringParams},
|
||||||
config::{Config, KeyModifiers, KeyPattern},
|
config::Config,
|
||||||
utils::prelude::*,
|
utils::prelude::*,
|
||||||
wayland::{
|
wayland::{
|
||||||
handlers::{
|
handlers::{
|
||||||
|
|
@ -78,16 +80,14 @@ mod workspace;
|
||||||
pub use self::element::{CosmicMapped, CosmicMappedRenderElement, CosmicSurface};
|
pub use self::element::{CosmicMapped, CosmicMappedRenderElement, CosmicSurface};
|
||||||
pub use self::seats::*;
|
pub use self::seats::*;
|
||||||
pub use self::workspace::*;
|
pub use self::workspace::*;
|
||||||
|
|
||||||
use self::{
|
use self::{
|
||||||
element::{
|
element::{
|
||||||
resize_indicator::{resize_indicator, ResizeIndicator},
|
resize_indicator::{resize_indicator, ResizeIndicator},
|
||||||
swap_indicator::{swap_indicator, SwapIndicator},
|
swap_indicator::{swap_indicator, SwapIndicator},
|
||||||
CosmicWindow, MaximizedState,
|
CosmicWindow, MaximizedState,
|
||||||
},
|
},
|
||||||
focus::{
|
focus::target::{KeyboardFocusTarget, PointerFocusTarget},
|
||||||
target::{KeyboardFocusTarget, PointerFocusTarget},
|
|
||||||
FocusDirection,
|
|
||||||
},
|
|
||||||
grabs::{
|
grabs::{
|
||||||
tab_items, window_items, GrabStartData, Item, MenuGrab, MoveGrab, ReleaseMode, ResizeEdge,
|
tab_items, window_items, GrabStartData, Item, MenuGrab, MoveGrab, ReleaseMode, ResizeEdge,
|
||||||
ResizeGrab,
|
ResizeGrab,
|
||||||
|
|
@ -106,8 +106,8 @@ const MOVE_GRAB_Y_OFFSET: f64 = 16.;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Trigger {
|
pub enum Trigger {
|
||||||
KeyboardSwap(KeyPattern, NodeDesc),
|
KeyboardSwap(shortcuts::Binding, NodeDesc),
|
||||||
KeyboardMove(KeyModifiers),
|
KeyboardMove(shortcuts::Modifiers),
|
||||||
Pointer(u32),
|
Pointer(u32),
|
||||||
Touch(TouchSlot),
|
Touch(TouchSlot),
|
||||||
}
|
}
|
||||||
|
|
@ -141,16 +141,10 @@ impl OverviewMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, serde::Deserialize, PartialEq, Eq, Hash)]
|
|
||||||
pub enum ResizeDirection {
|
|
||||||
Inwards,
|
|
||||||
Outwards,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum ResizeMode {
|
pub enum ResizeMode {
|
||||||
None,
|
None,
|
||||||
Started(KeyPattern, Instant, ResizeDirection),
|
Started(shortcuts::Binding, Instant, ResizeDirection),
|
||||||
Ended(Instant, ResizeDirection),
|
Ended(Instant, ResizeDirection),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1596,7 +1590,7 @@ impl Shell {
|
||||||
|
|
||||||
pub fn set_resize_mode(
|
pub fn set_resize_mode(
|
||||||
&mut self,
|
&mut self,
|
||||||
enabled: Option<(KeyPattern, ResizeDirection)>,
|
enabled: Option<(shortcuts::Binding, ResizeDirection)>,
|
||||||
config: &Config,
|
config: &Config,
|
||||||
evlh: LoopHandle<'static, crate::state::State>,
|
evlh: LoopHandle<'static, crate::state::State>,
|
||||||
) {
|
) {
|
||||||
|
|
@ -2306,14 +2300,14 @@ impl Shell {
|
||||||
is_sticky,
|
is_sticky,
|
||||||
tiling_enabled,
|
tiling_enabled,
|
||||||
edge,
|
edge,
|
||||||
&config.static_conf,
|
config,
|
||||||
)) as Box<dyn Iterator<Item = Item>>
|
)) as Box<dyn Iterator<Item = Item>>
|
||||||
} else {
|
} else {
|
||||||
let (tab, _) = mapped
|
let (tab, _) = mapped
|
||||||
.windows()
|
.windows()
|
||||||
.find(|(s, _)| s.wl_surface().as_deref() == Some(surface))
|
.find(|(s, _)| s.wl_surface().as_deref() == Some(surface))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
Box::new(tab_items(&mapped, &tab, is_tiled, &config.static_conf))
|
Box::new(tab_items(&mapped, &tab, is_tiled, config))
|
||||||
as Box<dyn Iterator<Item = Item>>
|
as Box<dyn Iterator<Item = Item>>
|
||||||
},
|
},
|
||||||
global_position,
|
global_position,
|
||||||
|
|
|
||||||
|
|
@ -192,26 +192,6 @@ pub enum ManagedLayer {
|
||||||
Sticky,
|
Sticky,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, serde::Deserialize, Clone, Copy, PartialEq, Eq)]
|
|
||||||
pub enum Direction {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
Up,
|
|
||||||
Down,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::ops::Not for Direction {
|
|
||||||
type Output = Self;
|
|
||||||
fn not(self) -> Self::Output {
|
|
||||||
match self {
|
|
||||||
Direction::Left => Direction::Right,
|
|
||||||
Direction::Right => Direction::Left,
|
|
||||||
Direction::Up => Direction::Down,
|
|
||||||
Direction::Down => Direction::Up,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum FocusResult {
|
pub enum FocusResult {
|
||||||
None,
|
None,
|
||||||
|
|
|
||||||
|
|
@ -463,9 +463,11 @@ impl State {
|
||||||
let idle_inhibit_manager_state = IdleInhibitManagerState::new::<State>(&dh);
|
let idle_inhibit_manager_state = IdleInhibitManagerState::new::<State>(&dh);
|
||||||
let idle_inhibiting_surfaces = HashSet::new();
|
let idle_inhibiting_surfaces = HashSet::new();
|
||||||
|
|
||||||
let data_control_state = config.static_conf.data_control_enabled.then(|| {
|
let data_control_state = std::env::var("COSMIC_DATA_CONTROL_ENABLED")
|
||||||
DataControlState::new::<Self, _>(dh, Some(&primary_selection_state), |_| true)
|
.is_ok_and(|value| value == "1")
|
||||||
});
|
.then(|| {
|
||||||
|
DataControlState::new::<Self, _>(dh, Some(&primary_selection_state), |_| true)
|
||||||
|
});
|
||||||
|
|
||||||
let shell = Arc::new(RwLock::new(Shell::new(&config)));
|
let shell = Arc::new(RwLock::new(Shell::new(&config)));
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue