mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-25 16:08:32 +00:00
fix(core/eckhart): fix passphrase keyboard bug
- when multi tab key timer expires, the buttons are resetted only if the passphrase reached the max length - when the passphrase keyboard layout is swapped, the buttons are resetted [no changelog]
This commit is contained in:
parent
26a52a5ed4
commit
9494ba8896
@ -139,6 +139,7 @@ pub(crate) enum DisplayStyle {
|
|||||||
Hidden,
|
Hidden,
|
||||||
Shown,
|
Shown,
|
||||||
LastOnly,
|
LastOnly,
|
||||||
|
LastWithMarker,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The number and colors of fading icons to display.
|
/// The number and colors of fading icons to display.
|
||||||
|
@ -362,9 +362,14 @@ impl Component for Keypad {
|
|||||||
self.pressed = None;
|
self.pressed = None;
|
||||||
return Some(KeypadMsg::EraseLong);
|
return Some(KeypadMsg::EraseLong);
|
||||||
}
|
}
|
||||||
// Detect press of all special buttons for rendering purposes
|
// Detect press/release of all special buttons for rendering purposes
|
||||||
Some(ButtonMsg::Pressed) => {
|
Some(ButtonMsg::Pressed) => {
|
||||||
self.pressed = Some(button);
|
self.pressed = Some(button);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(ButtonMsg::Released) => {
|
||||||
|
self.pressed = None;
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -377,9 +382,14 @@ impl Component for Keypad {
|
|||||||
self.pressed = None;
|
self.pressed = None;
|
||||||
return Some(KeypadMsg::Key(idx));
|
return Some(KeypadMsg::Key(idx));
|
||||||
}
|
}
|
||||||
// Detect press of all key buttons for rendering purposes
|
// Detect press/release of all key buttons for rendering purposes
|
||||||
Some(ButtonMsg::Pressed) => {
|
Some(ButtonMsg::Pressed) => {
|
||||||
self.pressed = Some(KeypadButton::Key(idx));
|
self.pressed = Some(KeypadButton::Key(idx));
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(ButtonMsg::Released) => {
|
||||||
|
self.pressed = None;
|
||||||
|
return None;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +106,7 @@ const KEYBOARD: [[&str; KEY_COUNT]; PAGE_COUNT] = [
|
|||||||
|
|
||||||
const MAX_LENGTH: usize = 50; // max length of the passphrase
|
const MAX_LENGTH: usize = 50; // max length of the passphrase
|
||||||
const MAX_SHOWN_LEN: usize = 14; // max number of icons per line
|
const MAX_SHOWN_LEN: usize = 14; // max number of icons per line
|
||||||
const LAST_DIGIT_TIMEOUT_S: u32 = 1;
|
const LAST_DIGIT_TIMEOUT: Duration = Duration::from_secs(1);
|
||||||
|
|
||||||
const NEXT_BTN_WIDTH: i16 = 103;
|
const NEXT_BTN_WIDTH: i16 = 103;
|
||||||
const NEXT_BTN_PADDING: i16 = 14;
|
const NEXT_BTN_PADDING: i16 = 14;
|
||||||
@ -176,14 +176,13 @@ impl PassphraseKeyboard {
|
|||||||
if self.multi_tap.pending_key().is_some() {
|
if self.multi_tap.pending_key().is_some() {
|
||||||
// Clear the pending state.
|
// Clear the pending state.
|
||||||
self.multi_tap.clear_pending_state(ctx);
|
self.multi_tap.clear_pending_state(ctx);
|
||||||
self.input.marker = false;
|
self.input.display_style = DisplayStyle::LastOnly;
|
||||||
// the character has been added, show it for a bit and then hide it
|
// the character has been added, show it for a bit and then hide it
|
||||||
self.input
|
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||||
.last_char_timer
|
|
||||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
|
||||||
}
|
}
|
||||||
// Update keys.
|
// Update keys.
|
||||||
self.replace_keys_contents();
|
self.replace_keys_contents();
|
||||||
|
self.update_keypad_state(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_keys_contents(&mut self) {
|
fn replace_keys_contents(&mut self) {
|
||||||
@ -200,6 +199,8 @@ impl PassphraseKeyboard {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Update the keypad state based on the current passphrase and input state
|
||||||
|
/// Can be used only when no key is pressed
|
||||||
fn update_keypad_state(&mut self, ctx: &mut EventCtx) {
|
fn update_keypad_state(&mut self, ctx: &mut EventCtx) {
|
||||||
let keypad_state = match self.input.display_style {
|
let keypad_state = match self.input.display_style {
|
||||||
DisplayStyle::Shown => {
|
DisplayStyle::Shown => {
|
||||||
@ -304,21 +305,45 @@ impl Component for PassphraseKeyboard {
|
|||||||
}
|
}
|
||||||
Event::Timer(_) if self.multi_tap.timeout_event(event) => {
|
Event::Timer(_) if self.multi_tap.timeout_event(event) => {
|
||||||
self.multi_tap.clear_pending_state(ctx);
|
self.multi_tap.clear_pending_state(ctx);
|
||||||
self.input
|
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||||
.last_char_timer
|
self.input.display_style = DisplayStyle::LastOnly;
|
||||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
// Disable keypad when the passphrase reached the max length
|
||||||
self.input.marker = false;
|
if self.passphrase().len() == MAX_LENGTH {
|
||||||
self.update_keypad_state(ctx);
|
self.update_keypad_state(ctx);
|
||||||
|
}
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Input event has to be handled before the swipe so that swipe in the input
|
||||||
|
// area is not processed
|
||||||
|
match self.input.event(ctx, event) {
|
||||||
|
Some(PassphraseInputMsg::TouchStart) => {
|
||||||
|
self.multi_tap.clear_pending_state(ctx);
|
||||||
|
// Disable keypad.
|
||||||
|
self.update_keypad_state(ctx);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(PassphraseInputMsg::TouchEnd) => {
|
||||||
|
// Enable keypad.
|
||||||
|
self.update_keypad_state(ctx);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Swipe event has to be handled before the individual button events
|
||||||
if let Some(swipe) = self.page_swipe.event(ctx, event) {
|
if let Some(swipe) = self.page_swipe.event(ctx, event) {
|
||||||
// We have detected a horizontal swipe. Change the keyboard page.
|
match swipe {
|
||||||
self.on_page_change(ctx, swipe);
|
Direction::Left | Direction::Right => {
|
||||||
return None;
|
// We have detected a horizontal swipe. Change the keyboard page.
|
||||||
|
self.on_page_change(ctx, swipe);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ButtonMsg::Clicked) = self.next_btn.event(ctx, event) {
|
if let Some(ButtonMsg::Clicked) = self.next_btn.event(ctx, event) {
|
||||||
@ -333,16 +358,13 @@ impl Component for PassphraseKeyboard {
|
|||||||
if text.len() == 1 {
|
if text.len() == 1 {
|
||||||
// If the key has just one character, it is immediately applied and the last
|
// If the key has just one character, it is immediately applied and the last
|
||||||
// digit timer should be started
|
// digit timer should be started
|
||||||
self.input.marker = false;
|
self.input.display_style = DisplayStyle::LastOnly;
|
||||||
self.input
|
self.input.last_char_timer.start(ctx, LAST_DIGIT_TIMEOUT);
|
||||||
.last_char_timer
|
|
||||||
.start(ctx, Duration::from_secs(LAST_DIGIT_TIMEOUT_S));
|
|
||||||
} else {
|
} else {
|
||||||
// multi tap timer is runnig, the last digit timer should be stopped
|
// multi tap timer is runnig, the last digit timer should be stopped
|
||||||
self.input.last_char_timer.stop();
|
self.input.last_char_timer.stop();
|
||||||
self.input.marker = true;
|
self.input.display_style = DisplayStyle::LastWithMarker;
|
||||||
}
|
}
|
||||||
self.input.display_style = DisplayStyle::LastOnly;
|
|
||||||
self.update_keypad_state(ctx);
|
self.update_keypad_state(ctx);
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
@ -372,21 +394,6 @@ impl Component for PassphraseKeyboard {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.input.event(ctx, event) {
|
|
||||||
Some(PassphraseInputMsg::TouchStart) => {
|
|
||||||
self.multi_tap.clear_pending_state(ctx);
|
|
||||||
// Disable keypad.
|
|
||||||
self.update_keypad_state(ctx);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
Some(PassphraseInputMsg::TouchEnd) => {
|
|
||||||
// Enable keypad.
|
|
||||||
self.update_keypad_state(ctx);
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +440,6 @@ struct PassphraseInput {
|
|||||||
area: Rect,
|
area: Rect,
|
||||||
textbox: TextBox,
|
textbox: TextBox,
|
||||||
display_style: DisplayStyle,
|
display_style: DisplayStyle,
|
||||||
marker: bool,
|
|
||||||
last_char_timer: Timer,
|
last_char_timer: Timer,
|
||||||
shown_area: Rect,
|
shown_area: Rect,
|
||||||
}
|
}
|
||||||
@ -451,8 +457,7 @@ impl PassphraseInput {
|
|||||||
Self {
|
Self {
|
||||||
area: Rect::zero(),
|
area: Rect::zero(),
|
||||||
textbox: TextBox::empty(MAX_LENGTH),
|
textbox: TextBox::empty(MAX_LENGTH),
|
||||||
display_style: DisplayStyle::LastOnly,
|
display_style: DisplayStyle::Hidden,
|
||||||
marker: false,
|
|
||||||
last_char_timer: Timer::new(),
|
last_char_timer: Timer::new(),
|
||||||
shown_area: Rect::zero(),
|
shown_area: Rect::zero(),
|
||||||
}
|
}
|
||||||
@ -503,7 +508,7 @@ impl PassphraseInput {
|
|||||||
let hidden_area: Rect = self.area.inset(KEYBOARD_INPUT_INSETS);
|
let hidden_area: Rect = self.area.inset(KEYBOARD_INPUT_INSETS);
|
||||||
let style = theme::TEXT_MEDIUM;
|
let style = theme::TEXT_MEDIUM;
|
||||||
let pp_len = self.passphrase().len();
|
let pp_len = self.passphrase().len();
|
||||||
let last_char = self.display_style == DisplayStyle::LastOnly;
|
let last_char = self.display_style != DisplayStyle::Hidden;
|
||||||
|
|
||||||
let mut cursor = hidden_area.left_center().ofs(Offset::x(12));
|
let mut cursor = hidden_area.left_center().ofs(Offset::x(12));
|
||||||
|
|
||||||
@ -560,7 +565,7 @@ impl PassphraseInput {
|
|||||||
.render(target);
|
.render(target);
|
||||||
|
|
||||||
// Paint the pending marker.
|
// Paint the pending marker.
|
||||||
if self.marker {
|
if self.display_style == DisplayStyle::LastWithMarker {
|
||||||
render_pending_marker(target, cursor, last, style.text_font, style.text_color);
|
render_pending_marker(target, cursor, last, style.text_font, style.text_color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user