Files
archived-muda/src/platform_impl/gtk/accelerator.rs
2022-12-08 20:50:24 +02:00

191 lines
5.3 KiB
Rust

// Copyright 2022-2022 Tauri Programme within The Commons Conservancy
// SPDX-License-Identifier: Apache-2.0
// SPDX-License-Identifier: MIT
use gtk::{prelude::*, AccelGroup};
use keyboard_types::{Code, Modifiers};
use crate::accelerator::Accelerator;
pub fn to_gtk_mnemonic<S: AsRef<str>>(string: S) -> String {
string
.as_ref()
.replace("&&", "[~~]")
.replace('&', "_")
.replace("[~~]", "&&")
.replace("[~~]", "&")
}
pub fn from_gtk_mnemonic<S: AsRef<str>>(string: S) -> String {
string
.as_ref()
.replace("__", "[~~]")
.replace('_', "&")
.replace("[~~]", "__")
}
pub fn parse_accelerator(accelerator: &Accelerator) -> crate::Result<(gdk::ModifierType, u32)> {
let key = match &accelerator.key {
Code::KeyA => 'A' as u32,
Code::KeyB => 'B' as u32,
Code::KeyC => 'C' as u32,
Code::KeyD => 'D' as u32,
Code::KeyE => 'E' as u32,
Code::KeyF => 'F' as u32,
Code::KeyG => 'G' as u32,
Code::KeyH => 'H' as u32,
Code::KeyI => 'I' as u32,
Code::KeyJ => 'J' as u32,
Code::KeyK => 'K' as u32,
Code::KeyL => 'L' as u32,
Code::KeyM => 'M' as u32,
Code::KeyN => 'N' as u32,
Code::KeyO => 'O' as u32,
Code::KeyP => 'P' as u32,
Code::KeyQ => 'Q' as u32,
Code::KeyR => 'R' as u32,
Code::KeyS => 'S' as u32,
Code::KeyT => 'T' as u32,
Code::KeyU => 'U' as u32,
Code::KeyV => 'V' as u32,
Code::KeyW => 'W' as u32,
Code::KeyX => 'X' as u32,
Code::KeyY => 'Y' as u32,
Code::KeyZ => 'Z' as u32,
Code::Digit0 => '0' as u32,
Code::Digit1 => '1' as u32,
Code::Digit2 => '2' as u32,
Code::Digit3 => '3' as u32,
Code::Digit4 => '4' as u32,
Code::Digit5 => '5' as u32,
Code::Digit6 => '6' as u32,
Code::Digit7 => '7' as u32,
Code::Digit8 => '8' as u32,
Code::Digit9 => '9' as u32,
Code::Comma => ',' as u32,
Code::Minus => '-' as u32,
Code::Period => '.' as u32,
Code::Space => ' ' as u32,
Code::Equal => '=' as u32,
Code::Semicolon => ';' as u32,
Code::Slash => '/' as u32,
Code::Backslash => '\\' as u32,
Code::Quote => '\'' as u32,
Code::Backquote => '`' as u32,
Code::BracketLeft => '[' as u32,
Code::BracketRight => ']' as u32,
k => {
if let Some(gdk_key) = key_to_raw_key(k) {
*gdk_key
} else {
return Err(crate::Error::AcceleratorKeyNotSupported(*k));
}
}
};
Ok((modifiers_to_gdk_modifier_type(accelerator.mods), key))
}
pub fn register_accelerator<M: IsA<gtk::Widget>>(
item: &M,
accel_group: &AccelGroup,
accelerator: &Accelerator,
) {
if let Ok((mods, key)) = parse_accelerator(accelerator) {
item.add_accelerator("activate", accel_group, key, mods, gtk::AccelFlags::VISIBLE);
}
}
fn modifiers_to_gdk_modifier_type(modifiers: Modifiers) -> gdk::ModifierType {
let mut result = gdk::ModifierType::empty();
result.set(
gdk::ModifierType::MOD1_MASK,
modifiers.contains(Modifiers::ALT),
);
result.set(
gdk::ModifierType::CONTROL_MASK,
modifiers.contains(Modifiers::CONTROL),
);
result.set(
gdk::ModifierType::SHIFT_MASK,
modifiers.contains(Modifiers::SHIFT),
);
result.set(
gdk::ModifierType::META_MASK,
modifiers.contains(Modifiers::SUPER),
);
result
}
fn key_to_raw_key(src: &Code) -> Option<gdk::keys::Key> {
use gdk::keys::constants::*;
Some(match src {
Code::Escape => Escape,
Code::Backspace => BackSpace,
Code::Tab => Tab,
Code::Enter => Return,
Code::ControlLeft => Control_L,
Code::AltLeft => Alt_L,
Code::ShiftLeft => Shift_L,
Code::MetaLeft => Super_L,
Code::ControlRight => Control_R,
Code::AltRight => Alt_R,
Code::ShiftRight => Shift_R,
Code::MetaRight => Super_R,
Code::CapsLock => Caps_Lock,
Code::F1 => F1,
Code::F2 => F2,
Code::F3 => F3,
Code::F4 => F4,
Code::F5 => F5,
Code::F6 => F6,
Code::F7 => F7,
Code::F8 => F8,
Code::F9 => F9,
Code::F10 => F10,
Code::F11 => F11,
Code::F12 => F12,
Code::F13 => F13,
Code::F14 => F14,
Code::F15 => F15,
Code::F16 => F16,
Code::F17 => F17,
Code::F18 => F18,
Code::F19 => F19,
Code::F20 => F20,
Code::F21 => F21,
Code::F22 => F22,
Code::F23 => F23,
Code::F24 => F24,
Code::PrintScreen => Print,
Code::ScrollLock => Scroll_Lock,
// Pause/Break not audio.
Code::Pause => Pause,
Code::Insert => Insert,
Code::Delete => Delete,
Code::Home => Home,
Code::End => End,
Code::PageUp => Page_Up,
Code::PageDown => Page_Down,
Code::NumLock => Num_Lock,
Code::ArrowUp => Up,
Code::ArrowDown => Down,
Code::ArrowLeft => Left,
Code::ArrowRight => Right,
Code::ContextMenu => Menu,
Code::WakeUp => WakeUp,
_ => return None,
})
}