Add shortcut hint toggle with Super+F1

This commit is contained in:
Samuel Onoja committed 2026-10-01 12:30:35 +01:00
1 parent 2c95e5e80f
commit 2b9f30fa5d
11 files changed
+235 -30

No files matched your search

+34 -3
View File
@@ -514,6 +514,7 @@ pub enum BindingAction {
Expel,
ToggleFloating,
ToggleOverview,
ToggleKeybindingGuide,
}
impl Binding {
@@ -616,6 +617,7 @@ impl Binding {
BindingAction::Expel => "Move window out of column".into(),
BindingAction::ToggleFloating => "Toggle floating window".into(),
BindingAction::ToggleOverview => "Open or close overview".into(),
BindingAction::ToggleKeybindingGuide => "Open or close shortcut hint".into(),
};
let mut parts = Vec::new();
for (enabled, label) in [
@@ -1566,6 +1568,10 @@ fn parse_action(
no_argument()?;
Ok(BindingAction::ToggleOverview)
}
"toggle-keybinding-guide" => {
no_argument()?;
Ok(BindingAction::ToggleKeybindingGuide)
}
_ => Err(ConfigError::InvalidBinding(format!("unknown action {action:?}"))),
}
}
@@ -1606,6 +1612,7 @@ fn default_bindings() -> Vec<BindingConfig> {
binding("Super+]", "expel", None),
binding("Super+Shift+Space", "toggle-floating", None),
binding("Super+Tab", "toggle-overview", None),
binding("Super+F1", "toggle-keybinding-guide", None),
binding("Super+Escape", "workspace-back-and-forth", None),
binding("Super+Shift+E", "exit", None),
];
@@ -1888,6 +1895,30 @@ pub(crate) fn config_path() -> Option<PathBuf> {
mod tests {
use super::*;
#[test]
fn shortcut_hint_has_a_default_binding_and_can_be_rebound() {
let bindings = parse("").runtime_config().unwrap().bindings;
assert!(bindings.iter().any(|binding| binding.modifiers.logo
&& binding.trigger == BindingTrigger::Keysym(keysyms::KEY_F1)
&& binding.action == BindingAction::ToggleKeybindingGuide));
let bindings = parse(
"binding keys=\"Super+F1\" disabled=#true\nbinding keys=\"Super+F2\" action=\"toggle-keybinding-guide\"\n",
)
.runtime_config()
.unwrap()
.bindings;
assert!(
!bindings
.iter()
.any(|binding| binding.trigger == BindingTrigger::Keysym(keysyms::KEY_F1))
);
assert!(
bindings
.iter()
.any(|binding| binding.trigger == BindingTrigger::Keysym(keysyms::KEY_F2)
&& binding.action == BindingAction::ToggleKeybindingGuide)
);
}
#[test]
fn workspace_back_and_forth_config_is_optional_and_bindable() {
let defaults = Config::default().runtime_config().unwrap();
@@ -2372,7 +2403,7 @@ mod tests {
let input = config.input_settings().unwrap();
let bindings = config.bindings(&input).unwrap();
assert_eq!(bindings.len(), 49);
assert_eq!(bindings.len(), 50);
for (shift, action) in [
(false, BindingAction::ToggleMaximized),
(true, BindingAction::ToggleFullscreen),
@@ -2415,14 +2446,14 @@ mod tests {
let input = replaced.input_settings().unwrap();
let bindings = replaced.bindings(&input).unwrap();
assert_eq!(bindings.len(), 49);
assert_eq!(bindings.len(), 50);
assert!(bindings.iter().any(|binding| {
binding.action == BindingAction::Spawn(vec!["foot".to_owned(), "--app-id".to_owned(), "work".to_owned()])
}));
let input = unbound.input_settings().unwrap();
let bindings = unbound.bindings(&input).unwrap();
assert_eq!(bindings.len(), 48);
assert_eq!(bindings.len(), 49);
assert!(!bindings.iter().any(|binding| binding.action == BindingAction::Close));
}
+3
View File
@@ -1017,6 +1017,9 @@ impl Ferese {
BindingAction::Expel => self.expel_focused_window(),
BindingAction::ToggleFloating => self.toggle_focused_floating(),
BindingAction::ToggleOverview => self.toggle_overview(),
BindingAction::ToggleKeybindingGuide => {
self.toggle_keybinding_guide();
}
}
}
}
+8
View File
@@ -657,6 +657,14 @@ impl Ferese {
"toggle-maximized" => self.toggle_focused_maximized(),
"toggle-layout" => self.toggle_layout_mode(),
"toggle-overview" => self.toggle_overview(),
"toggle-keybinding-guide" => {
if !self.toggle_keybinding_guide() {
return Err(CommandError::new(
"unavailable",
"Shortcut hint requires an unlocked session and an updated Ferese shell",
));
}
}
"cycle-column-width" => self.cycle_focused_column_width(),
"center-column" => self.center_focused_column(),
"consume" => self.consume_focused_window(),
+19 -1
View File
@@ -12,7 +12,7 @@ use crate::private_client::ClientCapabilities;
use crate::state::ClientState;
pub(crate) fn init_global(display: &DisplayHandle) {
display.create_global::<Ferese, FereseShellManagerV1, _>(4, ());
display.create_global::<Ferese, FereseShellManagerV1, _>(5, ());
}
pub(crate) fn config_chunks(source: &str) -> Vec<&str> {
@@ -208,6 +208,24 @@ impl Ferese {
}
}
pub(crate) fn toggle_keybinding_guide(&mut self) -> bool {
if self.session_lock.active {
return false;
}
let Some(shell) = self
.shell_resources
.iter()
.filter_map(|shell| shell.upgrade().ok())
.find(|shell| shell.version() >= 5)
else {
tracing::warn!("shortcut hint requires the updated Ferese shell");
return false;
};
let output = self.focused_output().map_or_else(String::new, |output| output.name());
shell.toggle_keybinding_guide(output);
true
}
pub(crate) fn request_logout_confirmation(&mut self) {
if self.session_lock.active {
return;