Skip to content

Commit

Permalink
This PR fixes a bug with select all (CMD + A on MacOS) when using a t…
Browse files Browse the repository at this point in the history
…ext_input.

Previous behaviour: when selecting all (CMD + A) would delete the current text inside the input and replace the content with just the letter 'a'.

Now we check if the logo key (modifier key) has been pressed before checking any other key and save it to the state level. This way we can prevent any text being deleted when using the select all shortcut or text being entered at all when a modifier key is pressed (this behaviour matches other text input behaviour i.e text inputs in the browser etc...).
  • Loading branch information
ZakisM committed Nov 9, 2020
1 parent da1a3ee commit cd7fa73
Showing 1 changed file with 158 additions and 122 deletions.
280 changes: 158 additions & 122 deletions native/src/widget/text_input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,7 @@ where
Event::Keyboard(keyboard::Event::CharacterReceived(c))
if self.state.is_focused
&& self.state.is_pasting.is_none()
&& !self.state.is_logo_pressed
&& !c.is_control() =>
{
let mut editor =
Expand All @@ -332,160 +333,193 @@ where
Event::Keyboard(keyboard::Event::KeyPressed {
key_code,
modifiers,
}) if self.state.is_focused => match key_code {
keyboard::KeyCode::Enter => {
if let Some(on_submit) = self.on_submit.clone() {
messages.push(on_submit);
}
}) if self.state.is_focused => {
if platform::is_copy_paste_modifier_pressed(modifiers) {
self.state.is_logo_pressed = true;
}
keyboard::KeyCode::Backspace => {
if platform::is_jump_modifier_pressed(modifiers)
&& self.state.cursor.selection(&self.value).is_none()
{
if self.is_secure {
let cursor_pos = self.state.cursor.end(&self.value);
self.state.cursor.select_range(0, cursor_pos);
} else {
self.state.cursor.select_left_by_words(&self.value);

match key_code {
keyboard::KeyCode::Enter => {
if let Some(on_submit) = self.on_submit.clone() {
messages.push(on_submit);
}
}
keyboard::KeyCode::Backspace => {
if platform::is_jump_modifier_pressed(modifiers)
&& self
.state
.cursor
.selection(&self.value)
.is_none()
{
if self.is_secure {
let cursor_pos =
self.state.cursor.end(&self.value);
self.state.cursor.select_range(0, cursor_pos);
} else {
self.state
.cursor
.select_left_by_words(&self.value);
}
}

let mut editor =
Editor::new(&mut self.value, &mut self.state.cursor);
let mut editor = Editor::new(
&mut self.value,
&mut self.state.cursor,
);

editor.backspace();
editor.backspace();

let message = (self.on_change)(editor.contents());
messages.push(message);
}
keyboard::KeyCode::Delete => {
if platform::is_jump_modifier_pressed(modifiers)
&& self.state.cursor.selection(&self.value).is_none()
{
if self.is_secure {
let cursor_pos = self.state.cursor.end(&self.value);
self.state
.cursor
.select_range(cursor_pos, self.value.len());
} else {
self.state
let message = (self.on_change)(editor.contents());
messages.push(message);
}
keyboard::KeyCode::Delete => {
if platform::is_jump_modifier_pressed(modifiers)
&& self
.state
.cursor
.select_right_by_words(&self.value);
.selection(&self.value)
.is_none()
{
if self.is_secure {
let cursor_pos =
self.state.cursor.end(&self.value);
self.state
.cursor
.select_range(cursor_pos, self.value.len());
} else {
self.state
.cursor
.select_right_by_words(&self.value);
}
}
}

let mut editor =
Editor::new(&mut self.value, &mut self.state.cursor);
let mut editor = Editor::new(
&mut self.value,
&mut self.state.cursor,
);

editor.delete();
editor.delete();

let message = (self.on_change)(editor.contents());
messages.push(message);
}
keyboard::KeyCode::Left => {
if platform::is_jump_modifier_pressed(modifiers)
&& !self.is_secure
{
if modifiers.shift {
self.state.cursor.select_left_by_words(&self.value);
let message = (self.on_change)(editor.contents());
messages.push(message);
}
keyboard::KeyCode::Left => {
if platform::is_jump_modifier_pressed(modifiers)
&& !self.is_secure
{
if modifiers.shift {
self.state
.cursor
.select_left_by_words(&self.value);
} else {
self.state
.cursor
.move_left_by_words(&self.value);
}
} else if modifiers.shift {
self.state.cursor.select_left(&self.value)
} else {
self.state.cursor.move_left_by_words(&self.value);
self.state.cursor.move_left(&self.value);
}
} else if modifiers.shift {
self.state.cursor.select_left(&self.value)
} else {
self.state.cursor.move_left(&self.value);
}
}
keyboard::KeyCode::Right => {
if platform::is_jump_modifier_pressed(modifiers)
&& !self.is_secure
{
if modifiers.shift {
self.state
.cursor
.select_right_by_words(&self.value);
keyboard::KeyCode::Right => {
if platform::is_jump_modifier_pressed(modifiers)
&& !self.is_secure
{
if modifiers.shift {
self.state
.cursor
.select_right_by_words(&self.value);
} else {
self.state
.cursor
.move_right_by_words(&self.value);
}
} else if modifiers.shift {
self.state.cursor.select_right(&self.value)
} else {
self.state.cursor.move_right_by_words(&self.value);
self.state.cursor.move_right(&self.value);
}
} else if modifiers.shift {
self.state.cursor.select_right(&self.value)
} else {
self.state.cursor.move_right(&self.value);
}
}
keyboard::KeyCode::Home => {
if modifiers.shift {
self.state.cursor.select_range(
self.state.cursor.start(&self.value),
0,
);
} else {
self.state.cursor.move_to(0);
}
}
keyboard::KeyCode::End => {
if modifiers.shift {
self.state.cursor.select_range(
self.state.cursor.start(&self.value),
self.value.len(),
);
} else {
self.state.cursor.move_to(self.value.len());
keyboard::KeyCode::Home => {
if modifiers.shift {
self.state.cursor.select_range(
self.state.cursor.start(&self.value),
0,
);
} else {
self.state.cursor.move_to(0);
}
}
}
keyboard::KeyCode::V => {
if platform::is_copy_paste_modifier_pressed(modifiers) {
if let Some(clipboard) = clipboard {
let content = match self.state.is_pasting.take() {
Some(content) => content,
None => {
let content: String = clipboard
.content()
.unwrap_or(String::new())
.chars()
.filter(|c| !c.is_control())
.collect();

Value::new(&content)
}
};

let mut editor = Editor::new(
&mut self.value,
&mut self.state.cursor,
keyboard::KeyCode::End => {
if modifiers.shift {
self.state.cursor.select_range(
self.state.cursor.start(&self.value),
self.value.len(),
);
} else {
self.state.cursor.move_to(self.value.len());
}
}
keyboard::KeyCode::V => {
if self.state.is_logo_pressed {
if let Some(clipboard) = clipboard {
let content = match self.state.is_pasting.take()
{
Some(content) => content,
None => {
let content: String = clipboard
.content()
.unwrap_or(String::new())
.chars()
.filter(|c| !c.is_control())
.collect();

Value::new(&content)
}
};

editor.paste(content.clone());
let mut editor = Editor::new(
&mut self.value,
&mut self.state.cursor,
);

editor.paste(content.clone());

let message = (self.on_change)(editor.contents());
messages.push(message);
let message =
(self.on_change)(editor.contents());
messages.push(message);

self.state.is_pasting = Some(content);
self.state.is_pasting = Some(content);
}
} else {
self.state.is_pasting = None;
}
} else {
self.state.is_pasting = None;
}
}
keyboard::KeyCode::A => {
if platform::is_copy_paste_modifier_pressed(modifiers) {
self.state.cursor.select_all(&self.value);
keyboard::KeyCode::A => {
if self.state.is_logo_pressed {
self.state.cursor.select_all(&self.value);
}
}
keyboard::KeyCode::Escape => {
self.state.is_focused = false;
self.state.is_dragging = false;
self.state.is_logo_pressed = false;
self.state.is_pasting = None;
}
_ => {}
}
keyboard::KeyCode::Escape => {
self.state.is_focused = false;
self.state.is_dragging = false;
self.state.is_pasting = None;
}
_ => {}
},
}
Event::Keyboard(keyboard::Event::KeyReleased {
key_code, ..
}) => match key_code {
keyboard::KeyCode::V => {
self.state.is_pasting = None;
}
_ => {}
_ => {
self.state.is_logo_pressed = false;
}
},
_ => {}
}
Expand Down Expand Up @@ -651,6 +685,7 @@ where
pub struct State {
is_focused: bool,
is_dragging: bool,
is_logo_pressed: bool,
is_pasting: Option<Value>,
last_click: Option<mouse::Click>,
cursor: Cursor,
Expand All @@ -672,6 +707,7 @@ impl State {
Self {
is_focused: true,
is_dragging: false,
is_logo_pressed: false,
is_pasting: None,
last_click: None,
cursor: Cursor::default(),
Expand Down

0 comments on commit cd7fa73

Please sign in to comment.