Make text cursor always appear on click (#5420)
<!-- Please read the "Making a PR" section of [`CONTRIBUTING.md`](https://github.com/emilk/egui/blob/master/CONTRIBUTING.md) before opening a Pull Request! * Keep your PR:s small and focused. * The PR title is what ends up in the changelog, so make it descriptive! * If applicable, add a screenshot or gif. * If it is a non-trivial addition, consider adding a demo for it to `egui_demo_lib`, or a new example. * Do NOT open PR:s from your `master` branch, as that makes it hard for maintainers to test and add commits to your PR. * Remember to run `cargo fmt` and `cargo clippy`. * Open the PR as a draft until you have self-reviewed it and run `./scripts/check.sh`. * When you have addressed a PR comment, mark it as resolved. Please be patient! I will review your PR, but my time is limited! --> * [x] I have followed the instructions in the PR template ### Problem When clicking on a TextEdit sometimes the cursor doesn't appear immediately which makes it feel like the click was not registered for a second. This is because the start time for the blinking animation is only reset on keyboard input, but not on mouse interaction. It's hard to tell on the video but the cursor doesn't show immediately after clicking if the blink timer happens to be off. https://github.com/user-attachments/assets/9f049bd0-0375-4291-b2ef-697777fb854d ### Solution Reset the click timer every time a `TextEdit` is clicked. Additionally, the cursor is now correctly painted on the pixel boundary. IMO we should default to 1px cursor (instead of 2px) but that's not included in this PR. Happy to make that change too. https://github.com/user-attachments/assets/6c489414-f2c4-4dc6-85dd-f8bc457edad0
This commit is contained in:
parent
eac7ba01fa
commit
cd0f5859b2
|
|
@ -96,8 +96,19 @@ pub fn paint_text_selection(
|
|||
pub fn paint_cursor_end(painter: &Painter, visuals: &Visuals, cursor_rect: Rect) {
|
||||
let stroke = visuals.text_cursor.stroke;
|
||||
|
||||
let top = cursor_rect.center_top();
|
||||
let bottom = cursor_rect.center_bottom();
|
||||
// Ensure the cursor is aligned to the pixel grid for whole number widths.
|
||||
// See https://github.com/emilk/egui/issues/5164
|
||||
let (top, bottom) = if (stroke.width as usize) % 2 == 0 {
|
||||
(
|
||||
painter.round_pos_to_pixels(cursor_rect.center_top()),
|
||||
painter.round_pos_to_pixels(cursor_rect.center_bottom()),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
painter.round_pos_to_pixel_center(cursor_rect.center_top()),
|
||||
painter.round_pos_to_pixel_center(cursor_rect.center_bottom()),
|
||||
)
|
||||
};
|
||||
|
||||
painter.line_segment([top, bottom], (stroke.width, stroke.color));
|
||||
|
||||
|
|
@ -121,14 +132,14 @@ pub fn paint_text_cursor(
|
|||
ui: &Ui,
|
||||
painter: &Painter,
|
||||
primary_cursor_rect: Rect,
|
||||
time_since_last_edit: f64,
|
||||
time_since_last_interaction: f64,
|
||||
) {
|
||||
if ui.visuals().text_cursor.blink {
|
||||
let on_duration = ui.visuals().text_cursor.on_duration;
|
||||
let off_duration = ui.visuals().text_cursor.off_duration;
|
||||
let total_duration = on_duration + off_duration;
|
||||
|
||||
let time_in_cycle = (time_since_last_edit % (total_duration as f64)) as f32;
|
||||
let time_in_cycle = (time_since_last_interaction % (total_duration as f64)) as f32;
|
||||
|
||||
let wake_in = if time_in_cycle < on_duration {
|
||||
// Cursor is visible
|
||||
|
|
|
|||
|
|
@ -603,6 +603,8 @@ impl<'t> TextEdit<'t> {
|
|||
|
||||
if did_interact || response.clicked() {
|
||||
ui.memory_mut(|mem| mem.request_focus(response.id));
|
||||
|
||||
state.last_interaction_time = ui.ctx().input(|i| i.time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -746,7 +748,7 @@ impl<'t> TextEdit<'t> {
|
|||
if text.is_mutable() && interactive {
|
||||
let now = ui.ctx().input(|i| i.time);
|
||||
if response.changed || selection_changed {
|
||||
state.last_edit_time = now;
|
||||
state.last_interaction_time = now;
|
||||
}
|
||||
|
||||
// Only show (and blink) cursor if the egui viewport has focus.
|
||||
|
|
@ -759,7 +761,7 @@ impl<'t> TextEdit<'t> {
|
|||
ui,
|
||||
&painter,
|
||||
primary_cursor_rect,
|
||||
now - state.last_edit_time,
|
||||
now - state.last_interaction_time,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ pub struct TextEditState {
|
|||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub(crate) singleline_offset: f32,
|
||||
|
||||
/// When did the user last press a key?
|
||||
/// When did the user last press a key or click on the `TextEdit`.
|
||||
/// Used to pause the cursor animation when typing.
|
||||
#[cfg_attr(feature = "serde", serde(skip))]
|
||||
pub(crate) last_edit_time: f64,
|
||||
pub(crate) last_interaction_time: f64,
|
||||
}
|
||||
|
||||
impl TextEditState {
|
||||
|
|
|
|||
Loading…
Reference in New Issue