From 68d456ac0b52b30b92c02250354ce76800973f56 Mon Sep 17 00:00:00 2001 From: RndUsr123 <150948884+RndUsr123@users.noreply.github.com> Date: Tue, 12 Aug 2025 10:27:55 +0000 Subject: [PATCH] Fixes sense issues in TextEdit when vertical alignment is used (#7436) * Closes * [ ] I have followed the instructions in the PR template I'm running a rustup-less rust install on Windows, so I don't have `clippy` nor `fmt` and can't run the .sh script. It's very little code and I manually tested this, so hopefully that's ok... Let me know if the comment in `state.rs` needs to be updated or the `text_offset` name isn't clear enough. --------- Co-authored-by: Emil Ernerfeldt --- crates/egui/src/widgets/text_edit/builder.rs | 13 ++++++------- crates/egui/src/widgets/text_edit/state.rs | 7 ++++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/egui/src/widgets/text_edit/builder.rs b/crates/egui/src/widgets/text_edit/builder.rs index 4df736e3..f46776b7 100644 --- a/crates/egui/src/widgets/text_edit/builder.rs +++ b/crates/egui/src/widgets/text_edit/builder.rs @@ -581,9 +581,8 @@ impl TextEdit<'_> { // TODO(emilk): drag selected text to either move or clone (ctrl on windows, alt on mac) - let singleline_offset = vec2(state.singleline_offset, 0.0); let cursor_at_pointer = - galley.cursor_from_pos(pointer_pos - rect.min + singleline_offset); + galley.cursor_from_pos(pointer_pos - rect.min + state.text_offset); if ui.visuals().text_cursor.preview && response.hovered() @@ -653,16 +652,16 @@ impl TextEdit<'_> { .align_size_within_rect(galley.size(), rect) .intersect(rect) // limit pos to the response rect area .min; - let align_offset = rect.left() - galley_pos.x; + let align_offset = rect.left_top() - galley_pos; // Visual clipping for singleline text editor with text larger than width - if clip_text && align_offset == 0.0 { + if clip_text && align_offset.x == 0.0 { let cursor_pos = match (cursor_range, ui.memory(|mem| mem.has_focus(id))) { (Some(cursor_range), true) => galley.pos_from_cursor(cursor_range.primary).min.x, _ => 0.0, }; - let mut offset_x = state.singleline_offset; + let mut offset_x = state.text_offset.x; let visible_range = offset_x..=offset_x + desired_inner_size.x; if !visible_range.contains(&cursor_pos) { @@ -677,10 +676,10 @@ impl TextEdit<'_> { .at_most(galley.size().x - desired_inner_size.x) .at_least(0.0); - state.singleline_offset = offset_x; + state.text_offset = vec2(offset_x, align_offset.y); galley_pos -= vec2(offset_x, 0.0); } else { - state.singleline_offset = align_offset; + state.text_offset = align_offset; } let selection_changed = if let (Some(cursor_range), Some(prev_cursor_range)) = diff --git a/crates/egui/src/widgets/text_edit/state.rs b/crates/egui/src/widgets/text_edit/state.rs index 11304e70..5827aac4 100644 --- a/crates/egui/src/widgets/text_edit/state.rs +++ b/crates/egui/src/widgets/text_edit/state.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use crate::mutex::Mutex; use crate::{ - Context, Id, + Context, Id, Vec2, text_selection::{CCursorRange, TextCursorState}, }; @@ -49,9 +49,10 @@ pub struct TextEditState { #[cfg_attr(feature = "serde", serde(skip))] pub(crate) ime_cursor_range: CCursorRange, - // Visual offset when editing singleline text bigger than the width. + // Text offset within the widget area. + // Used for sensing and singleline text clipping. #[cfg_attr(feature = "serde", serde(skip))] - pub(crate) singleline_offset: f32, + pub(crate) text_offset: Vec2, /// When did the user last press a key or click on the `TextEdit`. /// Used to pause the cursor animation when typing.