Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Modifier-only keybindings #187

Merged
merged 3 commits into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion config.ron
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
(modifiers: [Super], key: "a"): Spawn("busctl --user call com.system76.CosmicAppLibrary /com/system76/CosmicAppLibrary com.system76.CosmicAppLibrary Toggle"),
(modifiers: [Super], key: "w"): Spawn("busctl --user call com.system76.CosmicWorkspaces /com/system76/CosmicWorkspaces com.system76.CosmicWorkspaces Toggle"),
(modifiers: [Super], key: "slash"): Spawn("busctl --user call com.system76.CosmicLauncher /com/system76/CosmicLauncher com.system76.CosmicLauncher Toggle"),
(modifiers: [Super]): Spawn("busctl --user call com.system76.CosmicLauncher /com/system76/CosmicLauncher com.system76.CosmicLauncher Toggle"),

(modifiers: [], key: "XF86AudioRaiseVolume"): Spawn("amixer sset Master 5%+"),
(modifiers: [], key: "XF86AudioLowerVolume"): Spawn("amixer sset Master 5%-"),
Expand All @@ -86,4 +87,4 @@
workspace_amount: Dynamic,
workspace_layout: Vertical,
tiling_enabled: false,
)
)
15 changes: 10 additions & 5 deletions src/config/key_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,12 @@ pub struct KeyPattern {
#[serde(deserialize_with = "deserialize_KeyModifiers")]
pub modifiers: KeyModifiers,
/// The actual key, that was pressed
#[serde(deserialize_with = "deserialize_Keysym")]
pub key: u32,
#[serde(deserialize_with = "deserialize_Keysym", default)]
pub key: Option<u32>,
Drakulix marked this conversation as resolved.
Show resolved Hide resolved
}

impl KeyPattern {
pub fn new(modifiers: impl Into<KeyModifiers>, key: u32) -> KeyPattern {
pub fn new(modifiers: impl Into<KeyModifiers>, key: Option<u32>) -> KeyPattern {
KeyPattern {
modifiers: modifiers.into(),
key,
Expand All @@ -117,7 +117,12 @@ impl ToString for KeyPattern {
if self.modifiers.shift {
result += "Shift+";
}
result += &keysym_get_name(self.key);

if let Some(key) = self.key {
result += &keysym_get_name(key);
} else {
result.remove(result.len() - 1);
}
result
}
}
Expand Down Expand Up @@ -176,7 +181,7 @@ fn insert_binding(
for key in keys {
let pattern = KeyPattern {
modifiers: modifiers.clone(),
key,
key: Some(key),
};
if !key_bindings.contains_key(&pattern) {
key_bindings.insert(pattern, action.clone());
Expand Down
6 changes: 3 additions & 3 deletions src/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ where
}

#[allow(non_snake_case)]
pub fn deserialize_Keysym<'de, D>(deserializer: D) -> Result<Keysym, D::Error>
pub fn deserialize_Keysym<'de, D>(deserializer: D) -> Result<Option<Keysym>, D::Error>
where
D: serde::Deserializer<'de>,
{
Expand All @@ -76,9 +76,9 @@ where
name,
xkb::keysym_get_name(x)
);
Ok(x)
Ok(Some(x))
}
},
x => Ok(x),
x => Ok(Some(x)),
}
}
61 changes: 53 additions & 8 deletions src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub struct SeatId(pub usize);
pub struct ActiveOutput(pub RefCell<Output>);
#[derive(Default)]
pub struct SupressedKeys(RefCell<Vec<(u32, Option<RegistrationToken>)>>);
#[derive(Default, Debug)]
pub struct ModifiersShortcutQueue(RefCell<Option<KeyPattern>>);
#[derive(Default)]
pub struct Devices(RefCell<HashMap<String, Vec<DeviceCapability>>>);

Expand Down Expand Up @@ -107,6 +109,28 @@ impl SupressedKeys {
}
}

impl ModifiersShortcutQueue {
pub fn set(&self, binding: KeyPattern) {
let mut set = self.0.borrow_mut();
*set = Some(binding);
}

pub fn take(&self, binding: &KeyPattern) -> bool {
let mut set = self.0.borrow_mut();
if set.is_some() && set.as_ref().unwrap() == binding {
*set = None;
true
} else {
false
}
}

pub fn clear(&self) {
let mut set = self.0.borrow_mut();
*set = None;
}
}

impl Devices {
fn add_device<D: Device>(&self, device: &D) -> Vec<DeviceCapability> {
let id = device.id();
Expand Down Expand Up @@ -152,6 +176,7 @@ pub fn add_seat(
userdata.insert_if_missing(SeatId::default);
userdata.insert_if_missing(Devices::default);
userdata.insert_if_missing(SupressedKeys::default);
userdata.insert_if_missing(ModifiersShortcutQueue::default);
userdata.insert_if_missing(SeatMoveGrabState::default);
userdata.insert_if_missing(CursorState::default);
userdata.insert_if_missing(|| ActiveOutput(RefCell::new(output.clone())));
Expand Down Expand Up @@ -283,7 +308,7 @@ impl State {
|| (action_pattern.modifiers.alt && !modifiers.alt)
|| (action_pattern.modifiers.logo && !modifiers.logo)
|| (action_pattern.modifiers.shift && !modifiers.shift)
|| (handle.raw_syms().contains(&action_pattern.key) && state == KeyState::Released)
|| (action_pattern.key.is_some() && handle.raw_syms().contains(&action_pattern.key.unwrap()) && state == KeyState::Released)
{
data.common.shell.set_overview_mode(None, data.common.event_loop_handle.clone());

Expand Down Expand Up @@ -344,8 +369,8 @@ impl State {
if let (ResizeMode::Started(action_pattern, _, _), _) =
data.common.shell.resize_mode()
{
if state == KeyState::Released
&& handle.raw_syms().contains(&action_pattern.key)
if action_pattern.key.is_some() && state == KeyState::Released
&& handle.raw_syms().contains(&action_pattern.key.unwrap())
{
data.common.shell.set_resize_mode(None, &data.common.config, data.common.event_loop_handle.clone());
} else if action_pattern.modifiers != *modifiers {
Expand Down Expand Up @@ -390,7 +415,7 @@ impl State {
let action = Action::_ResizingInternal(direction, edge, state);
let key_pattern = KeyPattern {
modifiers: modifiers.clone().into(),
key: handle.raw_code(),
key: Some(handle.raw_code()),
};

if state == KeyState::Released {
Expand All @@ -412,7 +437,7 @@ impl State {
}).ok()
} else { None };

userdata
userdata
.get::<SupressedKeys>()
.unwrap()
.add(&handle, token);
Expand Down Expand Up @@ -472,14 +497,30 @@ impl State {
}

// handle the rest of the global shortcuts
let mut can_clear_modifiers_shortcut = true;
if !shortcuts_inhibited {
let modifiers_queue = userdata.get::<ModifiersShortcutQueue>().unwrap();
for (binding, action) in
data.common.config.static_conf.key_bindings.iter()
{
if state == KeyState::Pressed
&& binding.modifiers == *modifiers
&& handle.raw_syms().contains(&binding.key)
let modifiers_bypass = binding.key.is_none()
&& state == KeyState::Released
&& binding.modifiers != *modifiers
&& modifiers_queue.take(binding);

if !modifiers_bypass && binding.key.is_none() && state == KeyState::Pressed && binding.modifiers == *modifiers {
modifiers_queue.set(binding.clone());
can_clear_modifiers_shortcut = false;
}

if (
binding.key.is_some()
&& state == KeyState::Pressed
&& handle.raw_syms().contains(&binding.key.unwrap())
&& binding.modifiers == *modifiers
) || modifiers_bypass
{
modifiers_queue.clear();
userdata
.get::<SupressedKeys>()
.unwrap()
Expand All @@ -492,6 +533,10 @@ impl State {
}
}

if can_clear_modifiers_shortcut {
userdata.get::<ModifiersShortcutQueue>().unwrap().clear();
}

// keys are passed through to apps
FilterResult::Forward
},
Expand Down
4 changes: 2 additions & 2 deletions src/shell/layout/tiling/grabs/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl KeyboardGrab<State> for SwapWindowGrab {
(pattern.key, *direction)
})
.collect::<Vec<_>>();
let Some(direction) = syms.iter().find_map(|sym| focus_bindings.iter().find_map(|(key, direction)| (sym == key).then_some(*direction))) else { return };
let Some(direction) = syms.iter().find_map(|sym| focus_bindings.iter().find_map(|(key, direction)| (key.is_some() && sym == key.as_ref().unwrap()).then_some(*direction))) else { return };

data.handle_action(
Action::Focus(direction),
Expand All @@ -71,7 +71,7 @@ impl KeyboardGrab<State> for SwapWindowGrab {
time,
KeyPattern {
modifiers: modifiers.map(Into::into).unwrap_or_default(),
key: keycode,
key: Some(keycode),
},
None,
);
Expand Down