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 2 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
138 changes: 70 additions & 68 deletions config.ron
Original file line number Diff line number Diff line change
@@ -1,86 +1,88 @@
(
key_bindings: {
(modifiers: [Super, Shift], key: "Escape"): Terminate,
(modifiers: [Super], key: "Escape"): Debug,
(modifiers: [Super], key: "q"): Close,
(modifiers: [Super, Shift], key: Some("Escape")): Terminate,
(modifiers: [Super], key: Some("Escape")): Debug,
(modifiers: [Super], key: Some("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], key: Some("1")): Workspace(1),
(modifiers: [Super], key: Some("2")): Workspace(2),
(modifiers: [Super], key: Some("3")): Workspace(3),
(modifiers: [Super], key: Some("4")): Workspace(4),
(modifiers: [Super], key: Some("5")): Workspace(5),
(modifiers: [Super], key: Some("6")): Workspace(6),
(modifiers: [Super], key: Some("7")): Workspace(7),
(modifiers: [Super], key: Some("8")): Workspace(8),
(modifiers: [Super], key: Some("9")): Workspace(9),
(modifiers: [Super], key: Some("0")): LastWorkspace,
(modifiers: [Super, Shift], key: Some("1")): MoveToWorkspace(1),
(modifiers: [Super, Shift], key: Some("2")): MoveToWorkspace(2),
(modifiers: [Super, Shift], key: Some("3")): MoveToWorkspace(3),
(modifiers: [Super, Shift], key: Some("4")): MoveToWorkspace(4),
(modifiers: [Super, Shift], key: Some("5")): MoveToWorkspace(5),
(modifiers: [Super, Shift], key: Some("6")): MoveToWorkspace(6),
(modifiers: [Super, Shift], key: Some("7")): MoveToWorkspace(7),
(modifiers: [Super, Shift], key: Some("8")): MoveToWorkspace(8),
(modifiers: [Super, Shift], key: Some("9")): MoveToWorkspace(9),
(modifiers: [Super, Shift], key: Some("0")): MoveToLastWorkspace,

(modifiers: [Super, Ctrl, Alt], key: "Down"): MoveToNextOutput,
(modifiers: [Super, Ctrl, Alt], key: "Up"): MoveToPreviousOutput,
(modifiers: [Super, Ctrl, Alt], key: "j"): MoveToNextOutput,
(modifiers: [Super, Ctrl, Alt], key: "k"): MoveToPreviousOutput,
(modifiers: [Super, Ctrl, Alt], key: Some("Down")): MoveToNextOutput,
(modifiers: [Super, Ctrl, Alt], key: Some("Up")): MoveToPreviousOutput,
(modifiers: [Super, Ctrl, Alt], key: Some("j")): MoveToNextOutput,
(modifiers: [Super, Ctrl, Alt], key: Some("k")): MoveToPreviousOutput,

(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: Some("Period")): NextOutput,
(modifiers: [Super], key: Some("Comma")): PreviousOutput,
(modifiers: [Super, Shift], key: Some("Period")): MoveToNextOutput,
(modifiers: [Super, Shift], key: Some("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], key: Some("Left")): Focus(Left),
(modifiers: [Super], key: Some("Right")): Focus(Right),
(modifiers: [Super], key: Some("Up")): Focus(Up),
(modifiers: [Super], key: Some("Down")): Focus(Down),
(modifiers: [Super], key: Some("h")): Focus(Left),
(modifiers: [Super], key: Some("j")): Focus(Down),
(modifiers: [Super], key: Some("k")): Focus(Up),
(modifiers: [Super], key: Some("l")): Focus(Right),
(modifiers: [Super], key: Some("u")): Focus(Out),
(modifiers: [Super], key: Some("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, Shift], key: Some("Left")): Move(Left),
(modifiers: [Super, Shift], key: Some("Right")): Move(Right),
(modifiers: [Super, Shift], key: Some("Up")): Move(Up),
(modifiers: [Super, Shift], key: Some("Down")): Move(Down),
(modifiers: [Super, Shift], key: Some("h")): Move(Left),
(modifiers: [Super, Shift], key: Some("j")): Move(Down),
(modifiers: [Super, Shift], key: Some("k")): Move(Up),
(modifiers: [Super, Shift], key: Some("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: Some("o")): ToggleOrientation,
(modifiers: [Super], key: Some("s")): ToggleStacking,
(modifiers: [Super], key: Some("y")): ToggleTiling,
(modifiers: [Super], key: Some("g")): ToggleWindowFloating,
(modifiers: [Super], key: Some("x")): SwapWindow,

(modifiers: [Super], key: "m"): Maximize,
(modifiers: [Super], key: "r"): Resizing(Outwards),
(modifiers: [Super, Shift], key: "r"): Resizing(Inwards),
(modifiers: [Super], key: Some("m")): Maximize,
(modifiers: [Super], key: Some("r")): Resizing(Outwards),
(modifiers: [Super, Shift], key: Some("r")): Resizing(Inwards),

//TODO: ability to select default web browser
(modifiers: [Super], key: "b"): Spawn("firefox"),
(modifiers: [Super], key: Some("b")): Spawn("firefox"),
//TODO: ability to select default file browser
(modifiers: [Super], key: "f"): Spawn("nautilus"),
(modifiers: [Super], key: Some("f")): Spawn("nautilus"),
//TODO: ability to select default terminal
(modifiers: [Super], key: "t"): Spawn("gnome-terminal"),
(modifiers: [Super], key: Some("t")): Spawn("gnome-terminal"),

(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], key: Some("a")): Spawn("busctl --user call com.system76.CosmicAppLibrary /com/system76/CosmicAppLibrary com.system76.CosmicAppLibrary Toggle"),
(modifiers: [Super], key: Some("w")): Spawn("busctl --user call com.system76.CosmicWorkspaces /com/system76/CosmicWorkspaces com.system76.CosmicWorkspaces Toggle"),
(modifiers: [Super], key: Some("slash")): Spawn("busctl --user call com.system76.CosmicLauncher /com/system76/CosmicLauncher com.system76.CosmicLauncher Toggle"),
(modifiers: [Super], key: None): 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%-"),
(modifiers: [], key: "XF86AudioMute"): Spawn("amixer sset Master 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"),

(modifiers: [], key: Some("XF86AudioRaiseVolume")): Spawn("amixer sset Master 5%+"),
(modifiers: [], key: Some("XF86AudioLowerVolume")): Spawn("amixer sset Master 5%-"),
(modifiers: [], key: Some("XF86AudioMute")): Spawn("amixer sset Master toggle"),
(modifiers: [], key: Some("XF86MonBrightnessUp")): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon IncreaseDisplayBrightness"),
(modifiers: [], key: Some("XF86MonBrightnessDown")): Spawn("busctl --user call com.system76.CosmicSettingsDaemon /com/system76/CosmicSettingsDaemon com.system76.CosmicSettingsDaemon DecreaseDisplayBrightness"),
},
workspace_mode: OutputBound,
workspace_amount: Dynamic,
Expand Down
13 changes: 9 additions & 4 deletions src/config/key_bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ pub struct KeyPattern {
pub modifiers: KeyModifiers,
/// The actual key, that was pressed
#[serde(deserialize_with = "deserialize_Keysym")]
pub key: u32,
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
13 changes: 9 additions & 4 deletions src/config/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,18 @@ 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>,
{
use serde::de::{Error, Unexpected};

let name = String::deserialize(deserializer)?;
let name: Option<String> = Option::deserialize(deserializer)?;
if name.is_none() {
return Ok(None);
}

let name = name.unwrap();
PixelDoted marked this conversation as resolved.
Show resolved Hide resolved
//let name = format!("KEY_{}", code);
match xkb::keysym_from_name(&name, xkb::KEYSYM_NO_FLAGS) {
KeySyms::KEY_NoSymbol => match xkb::keysym_from_name(&name, xkb::KEYSYM_CASE_INSENSITIVE) {
Expand All @@ -76,9 +81,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
Loading