diff --git a/jay-config/src/keyboard/mods.rs b/jay-config/src/keyboard/mods.rs index 80b1dea8..d2351f0c 100644 --- a/jay-config/src/keyboard/mods.rs +++ b/jay-config/src/keyboard/mods.rs @@ -36,6 +36,11 @@ pub const NUM: Modifiers = MOD2; /// Alias for `MOD4`. pub const LOGO: Modifiers = MOD4; +/// Synthetic modifier matching key release events. +/// +/// This can be used to execute a callback on key release. +pub const RELEASE: Modifiers = Modifiers(1 << 31); + impl BitOr for Modifiers { type Output = Self; diff --git a/src/ifs/wl_seat/event_handling.rs b/src/ifs/wl_seat/event_handling.rs index f39527ee..fee45519 100644 --- a/src/ifs/wl_seat/event_handling.rs +++ b/src/ifs/wl_seat/event_handling.rs @@ -37,7 +37,7 @@ use { }, isnt::std_1::primitive::IsntSlice2Ext, jay_config::keyboard::{ - mods::{Modifiers, CAPS, NUM}, + mods::{Modifiers, CAPS, NUM, RELEASE}, syms::KeySym, ModifiedKeySym, }, @@ -375,11 +375,13 @@ impl WlSeatGlobal { let mut shortcuts = SmallVec::<[_; 1]>::new(); let new_mods; { - if !self.state.lock.locked.get() && state == wl_keyboard::PRESSED { - let old_mods = xkb_state.mods(); + if !self.state.lock.locked.get() { + let mut mods = xkb_state.mods().mods_effective & !(CAPS.0 | NUM.0); + if state == wl_keyboard::RELEASED { + mods |= RELEASE.0; + } let keysyms = xkb_state.unmodified_keysyms(key); for &sym in keysyms { - let mods = old_mods.mods_effective & !(CAPS.0 | NUM.0); if let Some(mods) = self.shortcuts.get(&(mods, sym)) { shortcuts.push(ModifiedKeySym { mods, diff --git a/toml-config/src/config/parsers/modified_keysym.rs b/toml-config/src/config/parsers/modified_keysym.rs index 3320a257..b07855e9 100644 --- a/toml-config/src/config/parsers/modified_keysym.rs +++ b/toml-config/src/config/parsers/modified_keysym.rs @@ -7,7 +7,10 @@ use { toml::toml_span::{Span, SpannedExt}, }, jay_config::keyboard::{ - mods::{Modifiers, ALT, CAPS, CTRL, LOCK, LOGO, MOD1, MOD2, MOD3, MOD4, MOD5, NUM, SHIFT}, + mods::{ + Modifiers, ALT, CAPS, CTRL, LOCK, LOGO, MOD1, MOD2, MOD3, MOD4, MOD5, NUM, RELEASE, + SHIFT, + }, ModifiedKeySym, }, thiserror::Error, @@ -49,6 +52,7 @@ impl Parser for ModifiedKeysymParser { "alt" => ALT, "num" => NUM, "logo" => LOGO, + "release" => RELEASE, _ => match KEYSYMS.get(part) { Some(new) if sym.is_none() => { sym = Some(*new); diff --git a/toml-spec/spec/spec.generated.json b/toml-spec/spec/spec.generated.json index 81b1647e..e1069ecc 100644 --- a/toml-spec/spec/spec.generated.json +++ b/toml-spec/spec/spec.generated.json @@ -440,7 +440,7 @@ "$ref": "#/$defs/RepeatRate" }, "shortcuts": { - "description": "The compositor shortcuts.\n\nThe keys should be in the following format:\n\n```\n(MOD-)*KEYSYM\n```\n\n`MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`,\n`mod5`, `caps`, `alt`, `num`, or `logo`.\n\n`KEYSYM` should be the name of a keysym. The authorative location for these names\nis [1] with the `XKB_KEY_` prefix removed.\n\nThe keysym should be the unmodified keysym. E.g. `shift-q` not `shift-Q`.\n\n[1]: https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n", + "description": "The compositor shortcuts.\n\nThe keys should be in the following format:\n\n```\n(MOD-)*KEYSYM\n```\n\n`MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`,\n`mod5`, `caps`, `alt`, `num`, `logo`, or `release`.\n\nUsing the `release` modifier causes the shortcut to trigger when the key is\nreleased.\n\n`KEYSYM` should be the name of a keysym. The authorative location for these names\nis [1] with the `XKB_KEY_` prefix removed.\n\nThe keysym should be the unmodified keysym. E.g. `shift-q` not `shift-Q`.\n\n[1]: https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h\n\n- Example:\n\n ```toml\n [shortcuts]\n alt-q = \"quit\"\n ```\n", "type": "object", "additionalProperties": { "description": "", diff --git a/toml-spec/spec/spec.generated.md b/toml-spec/spec/spec.generated.md index 5032b4fd..15da4000 100644 --- a/toml-spec/spec/spec.generated.md +++ b/toml-spec/spec/spec.generated.md @@ -694,7 +694,10 @@ The table has the following fields: ``` `MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`, - `mod5`, `caps`, `alt`, `num`, or `logo`. + `mod5`, `caps`, `alt`, `num`, `logo`, or `release`. + + Using the `release` modifier causes the shortcut to trigger when the key is + released. `KEYSYM` should be the name of a keysym. The authorative location for these names is [1] with the `XKB_KEY_` prefix removed. diff --git a/toml-spec/spec/spec.yaml b/toml-spec/spec/spec.yaml index 9d79a882..3bd8d1a2 100644 --- a/toml-spec/spec/spec.yaml +++ b/toml-spec/spec/spec.yaml @@ -1705,7 +1705,10 @@ Config: ``` `MOD` should be one of `shift`, `lock`, `ctrl`, `mod1`, `mod2`, `mod3`, `mod4`, - `mod5`, `caps`, `alt`, `num`, or `logo`. + `mod5`, `caps`, `alt`, `num`, `logo`, or `release`. + + Using the `release` modifier causes the shortcut to trigger when the key is + released. `KEYSYM` should be the name of a keysym. The authorative location for these names is [1] with the `XKB_KEY_` prefix removed.