Skip to content
Open
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
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ endif

BIN = cosmic-settings-daemon
SYSTEM_ACTIONS_CONF = "$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.Shortcuts/v1/system_actions"
VIM_SYMBOLS_CONF = "$(DESTDIR)$(sharedir)/cosmic/com.system76.CosmicSettings.Shortcuts/v1/vim_symbols"
POLKIT_RULE = "$(DESTDIR)$(sharedir)/polkit-1/rules.d/cosmic-settings-daemon.rules"

all: $(BIN)
Expand All @@ -36,6 +37,7 @@ $(BIN): Cargo.toml Cargo.lock src/main.rs vendor-check
install:
install -Dm0755 "$(CARGO_TARGET_DIR)/$(TARGET)/$(BIN)" "$(DESTDIR)$(bindir)/$(BIN)"
install -Dm0644 "data/system_actions.ron" "$(SYSTEM_ACTIONS_CONF)"
install -Dm0644 "data/vim_symbols.ron" "$(VIM_SYMBOLS_CONF)"
install -Dm0644 "data/polkit-1/rules.d/cosmic-settings-daemon.rules" "$(POLKIT_RULE)"

## Cargo Vendoring
Expand Down
2 changes: 1 addition & 1 deletion config/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MPL-2.0

pub mod shortcuts;
pub use shortcuts::{Action, Binding, Shortcuts};
pub use shortcuts::{Action, Binding, Shortcuts, VimSymbols};
pub mod window_rules;
8 changes: 4 additions & 4 deletions config/src/shortcuts/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,10 +130,10 @@ impl Binding {
/// Get the inferred direction of a xkb key
pub fn inferred_direction(&self) -> Option<Direction> {
match self.key? {
xkb::Keysym::Left | xkb::Keysym::h | xkb::Keysym::H => Some(Direction::Left),
xkb::Keysym::Down | xkb::Keysym::j | xkb::Keysym::J => Some(Direction::Down),
xkb::Keysym::Up | xkb::Keysym::k | xkb::Keysym::K => Some(Direction::Up),
xkb::Keysym::Right | xkb::Keysym::l | xkb::Keysym::L => Some(Direction::Right),
xkb::Keysym::Left => Some(Direction::Left),
xkb::Keysym::Down => Some(Direction::Down),
xkb::Keysym::Up => Some(Direction::Up),
xkb::Keysym::Right => Some(Direction::Right),
_ => None,
}
}
Expand Down
104 changes: 103 additions & 1 deletion config/src/shortcuts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub use action::Action;

pub mod modifier;

use action::Direction;
pub use modifier::{Modifier, Modifiers, ModifiersDef};

mod binding;
Expand All @@ -14,10 +15,13 @@ pub mod sym;

use cosmic_config::cosmic_config_derive::CosmicConfigEntry;
use cosmic_config::{ConfigGet, CosmicConfigEntry};
use serde::de::Unexpected;
use serde::ser::SerializeMap;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::collections::HashMap;
use xkbcommon::xkb;
use sym::NO_SYMBOL;
use xkbcommon::xkb::{self, Keysym};

pub const ID: &str = "com.system76.CosmicSettings.Shortcuts";

Expand Down Expand Up @@ -74,6 +78,31 @@ pub fn system_actions(context: &cosmic_config::Config) -> SystemActions {
config
}

/// Get a map of vim symbols and their configured directions
pub fn vim_symbols(context: &cosmic_config::Config) -> VimSymbols {
let mut config = VimSymbols::default();

// Get the system config first
if let Ok(context) = cosmic_config::Config::system(ID, Config::VERSION) {
match context.get::<VimSymbolsImpl>("vim_symbols") {
Ok(vim_symbols) => config = vim_symbols.0,
Err(why) => {
tracing::error!("failed to read system shortcuts config 'vim_symbols': {why:?}")
}
}
}

// Then override it with the user's config
match context.get::<VimSymbolsImpl>("vim_symbols") {
Ok(user_config) => config.extend(user_config.0),
Err(why) => {
tracing::error!("failed to read local shortcuts config 'vim_symbols': {why:?}")
}
}

config
}

/// cosmic-config configuration state for `com.system76.CosmicSettings.Shortcuts`
#[derive(Clone, Debug, Default, PartialEq, CosmicConfigEntry)]
#[version = 1]
Expand All @@ -99,6 +128,79 @@ impl Config {
}
}

pub type VimSymbols = BTreeMap<Keysym, Direction>;

struct VimSymbolsImpl(VimSymbols);

impl Serialize for VimSymbolsImpl {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let mut map = serializer.serialize_map(Some(self.0.len()))?;
for (k, v) in self.0.iter() {
map.serialize_entry(&xkb::keysym_get_name(k.clone()), &v)?;
}
map.end()
}
}

struct VimSymbolsVisitor;

impl<'de> serde::de::Visitor<'de> for VimSymbolsVisitor {
type Value = VimSymbolsImpl;

fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("VimSymbols Map")
}

fn visit_map<A>(self, mut access: A) -> Result<Self::Value, A::Error>
where
A: serde::de::MapAccess<'de>,
{
let mut map = VimSymbols::new();

while let Some((keystring, dir)) =
access.next_entry::<&ron::value::RawValue, Direction>()?
{
match keystring.into_rust::<&str>() {
Ok(val) => {
let key = match xkb::keysym_from_name(val, xkb::KEYSYM_NO_FLAGS) {
x if x.raw() == NO_SYMBOL => {
match xkb::keysym_from_name(val, xkb::KEYSYM_CASE_INSENSITIVE) {
x if x.raw() == NO_SYMBOL => Err(<A::Error as serde::de::Error>::invalid_value(Unexpected::Str(val),&"One of the keysym names of xkbcommon.h without the 'KEY_' prefix")),
x => Ok(Some(x))
}
}
x => Ok(Some(x)),
}?;
if let Some(key) = key {
map.insert(key, dir);
}
}
Err(err) => {
tracing::warn!(
"Skipping over invalid Keysym ({}): {}",
keystring.get_ron(),
err
);
}
}
}

Ok(VimSymbolsImpl(map))
}
}

impl<'de> Deserialize<'de> for VimSymbolsImpl {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_map(VimSymbolsVisitor)
}
}

/// A map of defined key [Binding]s and their triggerable [Action]s
#[derive(Clone, Debug, Default, PartialEq, Serialize)]
#[serde(transparent)]
Expand Down
10 changes: 10 additions & 0 deletions data/vim_symbols.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"h": Left,
"h": Left,
"j": Down,
"J": Down,
"k": Up,
"K": Up,
"l": Right,
"L": Right,
}