config: add support for mod masks in shortcuts
This commit is contained in:
parent
27f30f8d28
commit
90dbde99ab
15 changed files with 501 additions and 92 deletions
|
|
@ -11,7 +11,10 @@ use {
|
|||
},
|
||||
exec::Command,
|
||||
input::{acceleration::AccelProfile, capability::Capability, InputDevice, Seat},
|
||||
keyboard::Keymap,
|
||||
keyboard::{
|
||||
mods::{Modifiers, RELEASE},
|
||||
Keymap,
|
||||
},
|
||||
logging::LogLevel,
|
||||
tasks::{JoinHandle, JoinSlot},
|
||||
theme::{colors::Colorable, sized::Resizable, Color},
|
||||
|
|
@ -64,12 +67,17 @@ fn ignore_panic(name: &str, f: impl FnOnce()) {
|
|||
}
|
||||
}
|
||||
|
||||
struct KeyHandler {
|
||||
mask: Modifiers,
|
||||
cb: Callback,
|
||||
}
|
||||
|
||||
pub(crate) struct Client {
|
||||
configure: extern "C" fn(),
|
||||
srv_data: *const u8,
|
||||
srv_unref: unsafe extern "C" fn(data: *const u8),
|
||||
srv_handler: unsafe extern "C" fn(data: *const u8, msg: *const u8, size: usize),
|
||||
key_handlers: RefCell<HashMap<(Seat, ModifiedKeySym), Callback>>,
|
||||
key_handlers: RefCell<HashMap<(Seat, ModifiedKeySym), KeyHandler>>,
|
||||
timer_handlers: RefCell<HashMap<Timer, Callback>>,
|
||||
response: RefCell<Vec<Response>>,
|
||||
on_new_seat: RefCell<Option<Callback<Seat>>>,
|
||||
|
|
@ -915,33 +923,45 @@ impl Client {
|
|||
keymap
|
||||
}
|
||||
|
||||
pub fn bind<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(
|
||||
pub fn bind_masked<F: FnMut() + 'static>(
|
||||
&self,
|
||||
seat: Seat,
|
||||
mod_sym: T,
|
||||
mut mod_mask: Modifiers,
|
||||
mod_sym: ModifiedKeySym,
|
||||
mut f: F,
|
||||
) {
|
||||
let mod_sym = mod_sym.into();
|
||||
mod_mask |= mod_sym.mods | RELEASE;
|
||||
let register = {
|
||||
let mut kh = self.key_handlers.borrow_mut();
|
||||
let f = cb(move |_| f());
|
||||
let cb = cb(move |_| f());
|
||||
match kh.entry((seat, mod_sym)) {
|
||||
Entry::Occupied(mut o) => {
|
||||
*o.get_mut() = f;
|
||||
false
|
||||
let o = o.get_mut();
|
||||
o.cb = cb;
|
||||
mem::replace(&mut o.mask, mod_mask) != mod_mask
|
||||
}
|
||||
Entry::Vacant(v) => {
|
||||
v.insert(f);
|
||||
v.insert(KeyHandler { mask: mod_mask, cb });
|
||||
true
|
||||
}
|
||||
}
|
||||
};
|
||||
if register {
|
||||
self.send(&ClientMessage::AddShortcut {
|
||||
seat,
|
||||
mods: mod_sym.mods,
|
||||
sym: mod_sym.sym,
|
||||
});
|
||||
let msg = if !mod_mask.0 == 0 {
|
||||
ClientMessage::AddShortcut {
|
||||
seat,
|
||||
mods: mod_sym.mods,
|
||||
sym: mod_sym.sym,
|
||||
}
|
||||
} else {
|
||||
ClientMessage::AddShortcut2 {
|
||||
seat,
|
||||
mods: mod_sym.mods,
|
||||
mod_mask,
|
||||
sym: mod_sym.sym,
|
||||
}
|
||||
};
|
||||
self.send(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1104,7 +1124,11 @@ impl Client {
|
|||
}
|
||||
ServerMessage::InvokeShortcut { seat, mods, sym } => {
|
||||
let ms = ModifiedKeySym { mods, sym };
|
||||
let handler = self.key_handlers.borrow_mut().get(&(seat, ms)).cloned();
|
||||
let handler = self
|
||||
.key_handlers
|
||||
.borrow_mut()
|
||||
.get(&(seat, ms))
|
||||
.map(|k| k.cb.clone());
|
||||
if let Some(handler) = handler {
|
||||
run_cb("shortcut", &handler, ());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -451,6 +451,12 @@ pub enum ClientMessage<'a> {
|
|||
seat: Seat,
|
||||
forward: bool,
|
||||
},
|
||||
AddShortcut2 {
|
||||
seat: Seat,
|
||||
mods: Modifiers,
|
||||
mod_mask: Modifiers,
|
||||
sym: KeySym,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ pub mod capability;
|
|||
use {
|
||||
crate::{
|
||||
input::{acceleration::AccelProfile, capability::Capability},
|
||||
keyboard::Keymap,
|
||||
keyboard::{mods::Modifiers, Keymap},
|
||||
Axis, Direction, ModifiedKeySym, Workspace,
|
||||
_private::{ipc::WorkspaceSource, DEFAULT_SEAT_NAME},
|
||||
video::Connector,
|
||||
|
|
@ -188,12 +188,37 @@ impl Seat {
|
|||
/// CapsLock and NumLock are ignored during modifier evaluation. Therefore, bindings
|
||||
/// containing these modifiers will never be invoked.
|
||||
pub fn bind<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(self, mod_sym: T, f: F) {
|
||||
get!().bind(self, mod_sym, f)
|
||||
self.bind_masked(Modifiers(!0), mod_sym, f)
|
||||
}
|
||||
|
||||
/// Creates a compositor-wide hotkey while ignoring some modifiers.
|
||||
///
|
||||
/// This is similar to `bind` except that only the masked modifiers are considered.
|
||||
///
|
||||
/// For example, if this function is invoked with `mod_mask = Modifiers::NONE` and
|
||||
/// `mod_sym = SYM_XF86AudioRaiseVolume`, then the callback will be invoked whenever
|
||||
/// `SYM_XF86AudioRaiseVolume` is pressed. Even if the user is simultaneously holding
|
||||
/// the shift key which would otherwise prevent the callback from taking effect.
|
||||
///
|
||||
/// For example, if this function is invoked with `mod_mask = CTRL | SHIFT` and
|
||||
/// `mod_sym = CTRL | SYM_x`, then the callback will be invoked whenever the user
|
||||
/// presses `ctrl+x` without pressing the shift key. Even if the user is
|
||||
/// simultaneously holding the alt key.
|
||||
///
|
||||
/// If `mod_sym` contains any modifiers, then these modifiers are automatically added
|
||||
/// to the mask. The synthetic `RELEASE` modifier is always added to the mask.
|
||||
pub fn bind_masked<T: Into<ModifiedKeySym>, F: FnMut() + 'static>(
|
||||
self,
|
||||
mod_mask: Modifiers,
|
||||
mod_sym: T,
|
||||
f: F,
|
||||
) {
|
||||
get!().bind_masked(self, mod_mask, mod_sym.into(), f)
|
||||
}
|
||||
|
||||
/// Unbinds a hotkey.
|
||||
pub fn unbind<T: Into<ModifiedKeySym>>(self, mod_sym: T) {
|
||||
get!().unbind(self, mod_sym)
|
||||
get!().unbind(self, mod_sym.into())
|
||||
}
|
||||
|
||||
/// Moves the keyboard focus of the seat in the specified direction.
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ use {
|
|||
#[derive(Serialize, Deserialize, Copy, Clone, Eq, PartialEq, Default, Hash, Debug)]
|
||||
pub struct Modifiers(pub u32);
|
||||
|
||||
impl Modifiers {
|
||||
/// No modifiers.
|
||||
pub const NONE: Self = Modifiers(0);
|
||||
}
|
||||
|
||||
/// The Shift modifier
|
||||
pub const SHIFT: Modifiers = Modifiers(1 << 0);
|
||||
/// The CapsLock modifier.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue