Merge pull request #3134 from sopvop/fix_text_input_cua
Fix TextInput copy/paste shortcuts for non latin keyboard layouts
This commit is contained in:
commit
e95f5248cb
3 changed files with 103 additions and 20 deletions
|
|
@ -30,6 +30,91 @@ impl Key {
|
||||||
Self::Unidentified => Key::Unidentified,
|
Self::Unidentified => Key::Unidentified,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Tries to convert this logical [`Key`] into its latin character, using the
|
||||||
|
/// [`Physical`] key provided for translation if it isn't already in latin.
|
||||||
|
///
|
||||||
|
/// Returns `None` if no latin variant could be found.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use iced_core::keyboard::key::{Key, Named, Physical, Code};
|
||||||
|
///
|
||||||
|
/// // Latin c
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Key::Character("c".into()).to_latin(Physical::Code(Code::KeyC)),
|
||||||
|
/// Some('c'),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// // Cyrillic с
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Key::Character("с".into()).to_latin(Physical::Code(Code::KeyC)),
|
||||||
|
/// Some('c'),
|
||||||
|
/// );
|
||||||
|
///
|
||||||
|
/// // Arrow Left
|
||||||
|
/// assert_eq!(
|
||||||
|
/// Key::Named(Named::ArrowLeft).to_latin(Physical::Code(Code::ArrowLeft)),
|
||||||
|
/// None,
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
|
pub fn to_latin(&self, physical_key: Physical) -> Option<char> {
|
||||||
|
let Self::Character(s) = self else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut chars = s.chars();
|
||||||
|
let c = chars.next()?;
|
||||||
|
|
||||||
|
if chars.next().is_none() && c <= '\u{ff}' {
|
||||||
|
return Some(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
let Physical::Code(code) = physical_key else {
|
||||||
|
return None;
|
||||||
|
};
|
||||||
|
|
||||||
|
let latin = match code {
|
||||||
|
Code::KeyA => 'a',
|
||||||
|
Code::KeyB => 'b',
|
||||||
|
Code::KeyC => 'c',
|
||||||
|
Code::KeyD => 'd',
|
||||||
|
Code::KeyE => 'e',
|
||||||
|
Code::KeyF => 'f',
|
||||||
|
Code::KeyG => 'g',
|
||||||
|
Code::KeyH => 'h',
|
||||||
|
Code::KeyI => 'i',
|
||||||
|
Code::KeyJ => 'j',
|
||||||
|
Code::KeyK => 'k',
|
||||||
|
Code::KeyL => 'l',
|
||||||
|
Code::KeyM => 'm',
|
||||||
|
Code::KeyN => 'n',
|
||||||
|
Code::KeyO => 'o',
|
||||||
|
Code::KeyP => 'p',
|
||||||
|
Code::KeyQ => 'q',
|
||||||
|
Code::KeyR => 'r',
|
||||||
|
Code::KeyS => 's',
|
||||||
|
Code::KeyT => 't',
|
||||||
|
Code::KeyU => 'u',
|
||||||
|
Code::KeyV => 'v',
|
||||||
|
Code::KeyW => 'w',
|
||||||
|
Code::KeyX => 'x',
|
||||||
|
Code::KeyY => 'y',
|
||||||
|
Code::KeyZ => 'z',
|
||||||
|
Code::Digit0 => '0',
|
||||||
|
Code::Digit1 => '1',
|
||||||
|
Code::Digit2 => '2',
|
||||||
|
Code::Digit3 => '3',
|
||||||
|
Code::Digit4 => '4',
|
||||||
|
Code::Digit5 => '5',
|
||||||
|
Code::Digit6 => '6',
|
||||||
|
Code::Digit7 => '7',
|
||||||
|
Code::Digit8 => '8',
|
||||||
|
Code::Digit9 => '9',
|
||||||
|
_ => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(latin)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Named> for Key {
|
impl From<Named> for Key {
|
||||||
|
|
|
||||||
|
|
@ -1160,6 +1160,10 @@ pub struct KeyPress {
|
||||||
///
|
///
|
||||||
/// You should use this key for any single key bindings (e.g. motions).
|
/// You should use this key for any single key bindings (e.g. motions).
|
||||||
pub modified_key: keyboard::Key,
|
pub modified_key: keyboard::Key,
|
||||||
|
/// The physical key pressed.
|
||||||
|
///
|
||||||
|
/// You should use this key for layout-independent bindings.
|
||||||
|
pub physical_key: keyboard::key::Physical,
|
||||||
/// The state of the keyboard modifiers.
|
/// The state of the keyboard modifiers.
|
||||||
pub modifiers: keyboard::Modifiers,
|
pub modifiers: keyboard::Modifiers,
|
||||||
/// The text produced by the key press.
|
/// The text produced by the key press.
|
||||||
|
|
@ -1174,6 +1178,7 @@ impl<Message> Binding<Message> {
|
||||||
let KeyPress {
|
let KeyPress {
|
||||||
key,
|
key,
|
||||||
modified_key,
|
modified_key,
|
||||||
|
physical_key,
|
||||||
modifiers,
|
modifiers,
|
||||||
text,
|
text,
|
||||||
status,
|
status,
|
||||||
|
|
@ -1183,21 +1188,13 @@ impl<Message> Binding<Message> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let combination = match key.as_ref() {
|
let combination = match key.to_latin(physical_key) {
|
||||||
keyboard::Key::Character("c") if modifiers.command() => {
|
Some('c') if modifiers.command() => Some(Self::Copy),
|
||||||
Some(Self::Copy)
|
Some('x') if modifiers.command() => Some(Self::Cut),
|
||||||
}
|
Some('v') if modifiers.command() && !modifiers.alt() => {
|
||||||
keyboard::Key::Character("x") if modifiers.command() => {
|
|
||||||
Some(Self::Cut)
|
|
||||||
}
|
|
||||||
keyboard::Key::Character("v")
|
|
||||||
if modifiers.command() && !modifiers.alt() =>
|
|
||||||
{
|
|
||||||
Some(Self::Paste)
|
Some(Self::Paste)
|
||||||
}
|
}
|
||||||
keyboard::Key::Character("a") if modifiers.command() => {
|
Some('a') if modifiers.command() => Some(Self::SelectAll),
|
||||||
Some(Self::SelectAll)
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1359,6 +1356,7 @@ impl<Message> Update<Message> {
|
||||||
Event::Keyboard(keyboard::Event::KeyPressed {
|
Event::Keyboard(keyboard::Event::KeyPressed {
|
||||||
key,
|
key,
|
||||||
modified_key,
|
modified_key,
|
||||||
|
physical_key,
|
||||||
modifiers,
|
modifiers,
|
||||||
text,
|
text,
|
||||||
..
|
..
|
||||||
|
|
@ -1374,6 +1372,7 @@ impl<Message> Update<Message> {
|
||||||
let key_press = KeyPress {
|
let key_press = KeyPress {
|
||||||
key: key.clone(),
|
key: key.clone(),
|
||||||
modified_key: modified_key.clone(),
|
modified_key: modified_key.clone(),
|
||||||
|
physical_key: *physical_key,
|
||||||
modifiers: *modifiers,
|
modifiers: *modifiers,
|
||||||
text: text.clone(),
|
text: text.clone(),
|
||||||
status,
|
status,
|
||||||
|
|
|
||||||
|
|
@ -902,6 +902,7 @@ where
|
||||||
key,
|
key,
|
||||||
text,
|
text,
|
||||||
modified_key,
|
modified_key,
|
||||||
|
physical_key,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
let state = state::<Renderer>(tree);
|
let state = state::<Renderer>(tree);
|
||||||
|
|
@ -909,8 +910,8 @@ where
|
||||||
if let Some(focus) = &mut state.is_focused {
|
if let Some(focus) = &mut state.is_focused {
|
||||||
let modifiers = state.keyboard_modifiers;
|
let modifiers = state.keyboard_modifiers;
|
||||||
|
|
||||||
match key.as_ref() {
|
match key.to_latin(*physical_key) {
|
||||||
keyboard::Key::Character("c")
|
Some('c')
|
||||||
if state.keyboard_modifiers.command()
|
if state.keyboard_modifiers.command()
|
||||||
&& !self.is_secure =>
|
&& !self.is_secure =>
|
||||||
{
|
{
|
||||||
|
|
@ -926,7 +927,7 @@ where
|
||||||
shell.capture_event();
|
shell.capture_event();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyboard::Key::Character("x")
|
Some('x')
|
||||||
if state.keyboard_modifiers.command()
|
if state.keyboard_modifiers.command()
|
||||||
&& !self.is_secure =>
|
&& !self.is_secure =>
|
||||||
{
|
{
|
||||||
|
|
@ -955,7 +956,7 @@ where
|
||||||
update_cache(state, &self.value);
|
update_cache(state, &self.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyboard::Key::Character("v")
|
Some('v')
|
||||||
if state.keyboard_modifiers.command()
|
if state.keyboard_modifiers.command()
|
||||||
&& !state.keyboard_modifiers.alt() =>
|
&& !state.keyboard_modifiers.alt() =>
|
||||||
{
|
{
|
||||||
|
|
@ -994,9 +995,7 @@ where
|
||||||
update_cache(state, &self.value);
|
update_cache(state, &self.value);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
keyboard::Key::Character("a")
|
Some('a') if state.keyboard_modifiers.command() => {
|
||||||
if state.keyboard_modifiers.command() =>
|
|
||||||
{
|
|
||||||
let cursor_before = state.cursor;
|
let cursor_before = state.cursor;
|
||||||
|
|
||||||
state.cursor.select_all(&self.value);
|
state.cursor.select_all(&self.value);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue