diff --git a/core/src/keyboard/modifiers.rs b/core/src/keyboard/modifiers.rs index e531510f..edbf6d38 100644 --- a/core/src/keyboard/modifiers.rs +++ b/core/src/keyboard/modifiers.rs @@ -84,4 +84,28 @@ impl Modifiers { is_pressed } + + /// Returns true if the "jump key" is pressed in the [`Modifiers`]. + /// + /// The "jump key" is the modifier key used to widen text motions. It is the `Alt` + /// key in macOS and the `Ctrl` key in other platforms. + pub fn jump(self) -> bool { + if cfg!(target_os = "macos") { + self.alt() + } else { + self.control() + } + } + + /// Returns true if the "command key" is pressed on a macOS device. + /// + /// This is relevant for macOS-specific actions (e.g. `⌘ + ArrowLeft` moves the cursor + /// to the beginning of the line). + pub fn macos_command(self) -> bool { + if cfg!(target_os = "macos") { + self.logo() + } else { + false + } + } } diff --git a/widget/src/text_editor.rs b/widget/src/text_editor.rs index 7c0b98ea..41b058af 100644 --- a/widget/src/text_editor.rs +++ b/widget/src/text_editor.rs @@ -768,9 +768,17 @@ impl Update { if let keyboard::Key::Named(named_key) = key.as_ref() { if let Some(motion) = motion(named_key) { - let motion = if platform::is_jump_modifier_pressed( - modifiers, - ) { + let motion = if modifiers.macos_command() { + match motion { + Motion::Left => Motion::Home, + Motion::Right => Motion::End, + _ => motion, + } + } else { + motion + }; + + let motion = if modifiers.jump() { motion.widen() } else { motion @@ -807,18 +815,6 @@ fn motion(key: key::Named) -> Option { } } -mod platform { - use crate::core::keyboard; - - pub fn is_jump_modifier_pressed(modifiers: keyboard::Modifiers) -> bool { - if cfg!(target_os = "macos") { - modifiers.alt() - } else { - modifiers.control() - } - } -} - /// The possible status of a [`TextEditor`]. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Status { diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index e9f07838..941e9bde 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -826,7 +826,7 @@ where } } keyboard::Key::Named(key::Named::Backspace) => { - if platform::is_jump_modifier_pressed(modifiers) + if modifiers.jump() && state.cursor.selection(&self.value).is_none() { if self.is_secure { @@ -850,7 +850,7 @@ where update_cache(state, &self.value); } keyboard::Key::Named(key::Named::Delete) => { - if platform::is_jump_modifier_pressed(modifiers) + if modifiers.jump() && state.cursor.selection(&self.value).is_none() { if self.is_secure { @@ -876,44 +876,6 @@ where update_cache(state, &self.value); } - keyboard::Key::Named(key::Named::ArrowLeft) => { - if platform::is_jump_modifier_pressed(modifiers) - && !self.is_secure - { - if modifiers.shift() { - state - .cursor - .select_left_by_words(&self.value); - } else { - state - .cursor - .move_left_by_words(&self.value); - } - } else if modifiers.shift() { - state.cursor.select_left(&self.value); - } else { - state.cursor.move_left(&self.value); - } - } - keyboard::Key::Named(key::Named::ArrowRight) => { - if platform::is_jump_modifier_pressed(modifiers) - && !self.is_secure - { - if modifiers.shift() { - state - .cursor - .select_right_by_words(&self.value); - } else { - state - .cursor - .move_right_by_words(&self.value); - } - } else if modifiers.shift() { - state.cursor.select_right(&self.value); - } else { - state.cursor.move_right(&self.value); - } - } keyboard::Key::Named(key::Named::Home) => { if modifiers.shift() { state.cursor.select_range( @@ -934,6 +896,64 @@ where state.cursor.move_to(self.value.len()); } } + keyboard::Key::Named(key::Named::ArrowLeft) + if modifiers.macos_command() => + { + if modifiers.shift() { + state.cursor.select_range( + state.cursor.start(&self.value), + 0, + ); + } else { + state.cursor.move_to(0); + } + } + keyboard::Key::Named(key::Named::ArrowRight) + if modifiers.macos_command() => + { + if modifiers.shift() { + state.cursor.select_range( + state.cursor.start(&self.value), + self.value.len(), + ); + } else { + state.cursor.move_to(self.value.len()); + } + } + keyboard::Key::Named(key::Named::ArrowLeft) => { + if modifiers.jump() && !self.is_secure { + if modifiers.shift() { + state + .cursor + .select_left_by_words(&self.value); + } else { + state + .cursor + .move_left_by_words(&self.value); + } + } else if modifiers.shift() { + state.cursor.select_left(&self.value); + } else { + state.cursor.move_left(&self.value); + } + } + keyboard::Key::Named(key::Named::ArrowRight) => { + if modifiers.jump() && !self.is_secure { + if modifiers.shift() { + state + .cursor + .select_right_by_words(&self.value); + } else { + state + .cursor + .move_right_by_words(&self.value); + } + } else if modifiers.shift() { + state.cursor.select_right(&self.value); + } else { + state.cursor.move_right(&self.value); + } + } keyboard::Key::Named(key::Named::Escape) => { state.is_focused = None; state.is_dragging = false; @@ -1281,18 +1301,6 @@ impl operation::TextInput for State

{ } } -mod platform { - use crate::core::keyboard; - - pub fn is_jump_modifier_pressed(modifiers: keyboard::Modifiers) -> bool { - if cfg!(target_os = "macos") { - modifiers.alt() - } else { - modifiers.control() - } - } -} - fn offset( text_bounds: Rectangle, value: &Value,