Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keyboard navigation: focus change loses new value in DragValue #2877

Closed
tajtiattila opened this issue Apr 6, 2023 · 2 comments · Fixed by #3776
Closed

Keyboard navigation: focus change loses new value in DragValue #2877

tajtiattila opened this issue Apr 6, 2023 · 2 comments · Fixed by #3776
Labels
bug Something is broken

Comments

@tajtiattila
Copy link

In the Widget Gallery of Egui Demo, focus the DragValue and type in a new number. Tab or Shift+Tab moves the focus to the next widget, but the new value is lost. The value is kept only when Enter is pressed, but then the focus is lost.

egui.demo.app.2023-04-06.09-19-40.mp4

This somewhat defeats keyboard navigation with DragValues because one can either navigate or change values, but not both.

Expected behavior
DragValue should keep the value entered when Tab is pressed.

Tested on the web demo at egui.rs and eframe on Windows using egui version 0.21.3-28-geb0812a9 (2023-03-31).

There seems to be a related issue: the internal state of the TextEdit/DragValue (text cursor position, selection) seems to be remembered when navigating away with Tab, and is reset only when focusing the widget with the mouse (which selects the whole number). Perhaps focusing the DragValue with Tab should work like focusing with the mouse.

@tajtiattila tajtiattila added the bug Something is broken label Apr 6, 2023
@harrisonmg
Copy link
Contributor

relevant: #2880

@YgorSouza
Copy link
Contributor

The code that decides whether the value should be updated is this:

let update = if update_while_editing {
// Update when the edit content has changed.
response.changed()
} else {
// Update only when the edit has lost focus.
response.lost_focus()
};

The code is conditional on the is_kb_editing variable defined here:

// The following ensures that when a `DragValue` receives focus,
// it is immediately rendered in edit mode, rather than being rendered
// in button mode for just one frame. This is important for
// screen readers.
let is_kb_editing = ui.memory_mut(|mem| {
mem.interested_in_focus(id);
let is_kb_editing = mem.has_focus(id);
if mem.gained_focus(id) {
mem.drag_value.edit_string = None;
}
is_kb_editing
});

It seems that the problem is that on the frame where the TextEdit would lose focus after pressing tab, is_kb_editing is already set to false, so we never get the lost_focus condition to update the value. We get it with Enter because in that case the TextEdit itself calls surrender_focus on the same frame:

Event::Key {
key: Key::Enter,
pressed: true,
..
} => {
if multiline {
let mut ccursor = delete_selected(text, &cursor_range);
insert_text(&mut ccursor, text, "\n", char_limit);
// TODO(emilk): if code editor, auto-indent by same leading tabs, + one if the lines end on an opening bracket
Some(CCursorRange::one(ccursor))
} else {
ui.memory_mut(|mem| mem.surrender_focus(id)); // End input with enter
break;
}
}

Given that, I wonder what would be the best way to fix it. Maybe we could change the logic for is_kb_editing to render an extra frame after focus is lost, but that would mess with accessibility, according to the comment. Another option would be to add a pub(crate) method to TextEdit that would make it capture the Tab key and surrender focus manually like it does with Enter, but that seems a little convoluted.

YgorSouza added a commit to YgorSouza/egui that referenced this issue Oct 8, 2023
YgorSouza added a commit to YgorSouza/egui that referenced this issue Oct 8, 2023
emilk added a commit that referenced this issue Jan 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something is broken
Projects
None yet
3 participants