Merge pull request #2315 from Brady-Simon/macos-command-input-behavior
Add Command + ArrowLeft/Right input behavior for macOS
This commit is contained in:
commit
06ff17fcf8
3 changed files with 95 additions and 67 deletions
|
|
@ -84,4 +84,28 @@ impl Modifiers {
|
||||||
|
|
||||||
is_pressed
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -768,9 +768,17 @@ impl Update {
|
||||||
|
|
||||||
if let keyboard::Key::Named(named_key) = key.as_ref() {
|
if let keyboard::Key::Named(named_key) = key.as_ref() {
|
||||||
if let Some(motion) = motion(named_key) {
|
if let Some(motion) = motion(named_key) {
|
||||||
let motion = if platform::is_jump_modifier_pressed(
|
let motion = if modifiers.macos_command() {
|
||||||
modifiers,
|
match motion {
|
||||||
) {
|
Motion::Left => Motion::Home,
|
||||||
|
Motion::Right => Motion::End,
|
||||||
|
_ => motion,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
motion
|
||||||
|
};
|
||||||
|
|
||||||
|
let motion = if modifiers.jump() {
|
||||||
motion.widen()
|
motion.widen()
|
||||||
} else {
|
} else {
|
||||||
motion
|
motion
|
||||||
|
|
@ -807,18 +815,6 @@ fn motion(key: key::Named) -> Option<Motion> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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`].
|
/// The possible status of a [`TextEditor`].
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum Status {
|
pub enum Status {
|
||||||
|
|
|
||||||
|
|
@ -826,7 +826,7 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
keyboard::Key::Named(key::Named::Backspace) => {
|
keyboard::Key::Named(key::Named::Backspace) => {
|
||||||
if platform::is_jump_modifier_pressed(modifiers)
|
if modifiers.jump()
|
||||||
&& state.cursor.selection(&self.value).is_none()
|
&& state.cursor.selection(&self.value).is_none()
|
||||||
{
|
{
|
||||||
if self.is_secure {
|
if self.is_secure {
|
||||||
|
|
@ -850,7 +850,7 @@ where
|
||||||
update_cache(state, &self.value);
|
update_cache(state, &self.value);
|
||||||
}
|
}
|
||||||
keyboard::Key::Named(key::Named::Delete) => {
|
keyboard::Key::Named(key::Named::Delete) => {
|
||||||
if platform::is_jump_modifier_pressed(modifiers)
|
if modifiers.jump()
|
||||||
&& state.cursor.selection(&self.value).is_none()
|
&& state.cursor.selection(&self.value).is_none()
|
||||||
{
|
{
|
||||||
if self.is_secure {
|
if self.is_secure {
|
||||||
|
|
@ -876,44 +876,6 @@ where
|
||||||
|
|
||||||
update_cache(state, &self.value);
|
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) => {
|
keyboard::Key::Named(key::Named::Home) => {
|
||||||
if modifiers.shift() {
|
if modifiers.shift() {
|
||||||
state.cursor.select_range(
|
state.cursor.select_range(
|
||||||
|
|
@ -934,6 +896,64 @@ where
|
||||||
state.cursor.move_to(self.value.len());
|
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) => {
|
keyboard::Key::Named(key::Named::Escape) => {
|
||||||
state.is_focused = None;
|
state.is_focused = None;
|
||||||
state.is_dragging = false;
|
state.is_dragging = false;
|
||||||
|
|
@ -1281,18 +1301,6 @@ impl<P: text::Paragraph> operation::TextInput for State<P> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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<P: text::Paragraph>(
|
fn offset<P: text::Paragraph>(
|
||||||
text_bounds: Rectangle,
|
text_bounds: Rectangle,
|
||||||
value: &Value,
|
value: &Value,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue