Skip to content

Commit

Permalink
Fix hidden cursor when TextEdit is inside ScrollArea
Browse files Browse the repository at this point in the history
  • Loading branch information
juancampa committed Oct 13, 2024
1 parent 23728e1 commit d7bd15d
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 4 deletions.
22 changes: 21 additions & 1 deletion crates/egui/src/containers/scroll_area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,11 @@ struct Prepared {

scrolling_enabled: bool,
stick_to_end: Vec2b,

/// If there was a scroll target before the ScrollArea was added this frame, it's
/// not for us to handle so we save it and restore it after this ScrollArea is done.
saved_scroll_target: [Option<frame_state::ScrollTarget>; 2],

animated: bool,
}

Expand Down Expand Up @@ -693,6 +698,10 @@ impl ScrollArea {
}
}

let saved_scroll_target = content_ui
.ctx()
.frame_state_mut(|state| std::mem::take(&mut state.scroll_target));

Prepared {
id,
state,
Expand All @@ -707,6 +716,7 @@ impl ScrollArea {
viewport,
scrolling_enabled,
stick_to_end,
saved_scroll_target,
animated,
}
}
Expand Down Expand Up @@ -820,6 +830,7 @@ impl Prepared {
viewport: _,
scrolling_enabled,
stick_to_end,
saved_scroll_target,
animated,
} = self;

Expand Down Expand Up @@ -853,7 +864,7 @@ impl Prepared {
let (start, end) = (range.min, range.max);
let clip_start = clip_rect.min[d];
let clip_end = clip_rect.max[d];
let mut spacing = ui.spacing().item_spacing[d];
let mut spacing = content_ui.spacing().item_spacing[d];

let delta_update = if let Some(align) = align {
let center_factor = align.to_factor();
Expand Down Expand Up @@ -902,6 +913,15 @@ impl Prepared {
}
}

// Restore scroll target meant for ScrollAreas up the stack (if any)
ui.ctx().frame_state_mut(|state| {
for d in 0..2 {
if saved_scroll_target[d].is_some() {
state.scroll_target[d] = saved_scroll_target[d].clone();
};
}
});

let inner_rect = {
// At this point this is the available size for the inner rect.
let mut inner_size = inner_rect.size();
Expand Down
16 changes: 13 additions & 3 deletions crates/egui/src/widgets/text_edit/builder.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::sync::Arc;

use emath::Rect;
use epaint::text::{cursor::CCursor, Galley, LayoutJob};

use crate::{
Expand Down Expand Up @@ -719,17 +720,26 @@ impl<'t> TextEdit<'t> {
}
}

// Allocate additional space if edits were made this frame that changed the size. This is important so that,
// if there's a ScrollArea, it can properly scroll to the cursor.
let extra_size = galley.size() - rect.size();
if extra_size.x > 0.0 || extra_size.y > 0.0 {
ui.allocate_rect(
Rect::from_min_size(outer_rect.max, extra_size),
Sense::hover(),
);
}

painter.galley(galley_pos, galley.clone(), text_color);

if has_focus {
if let Some(cursor_range) = state.cursor.range(&galley) {
let primary_cursor_rect =
cursor_rect(galley_pos, &galley, &cursor_range.primary, row_height);

let is_fully_visible = ui.clip_rect().contains_rect(rect); // TODO(emilk): remove this HACK workaround for https://github.com/emilk/egui/issues/1531
if (response.changed || selection_changed) && !is_fully_visible {
if response.changed || selection_changed {
// Scroll to keep primary cursor in view:
ui.scroll_to_rect(primary_cursor_rect, None);
ui.scroll_to_rect(primary_cursor_rect + margin, None);
}

if text.is_mutable() && interactive {
Expand Down

0 comments on commit d7bd15d

Please sign in to comment.