Merge pull request #8623 from penpot/superalex-fix-embedded-editor-cursor-positioning

🐛 Fix embedded editor cursor positioning
This commit is contained in:
Aitor Moreno 2026-03-13 12:21:12 +01:00 committed by GitHub
commit 39dcad8f54
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 17 additions and 10 deletions

View File

@ -123,9 +123,9 @@ fn calculate_cursor_rect(
.map(|span| span.text.chars().count()) .map(|span| span.text.chars().count())
.sum(); .sum();
let (cursor_x, cursor_height) = if para_char_count == 0 { let (cursor_x, cursor_y, cursor_height) = if para_char_count == 0 {
// Empty paragraph - use default height // Empty paragraph - use default height
(0.0, laid_out_para.height()) (0.0, 0.0, laid_out_para.height())
} else if char_pos == 0 { } else if char_pos == 0 {
let rects = laid_out_para.get_rects_for_range( let rects = laid_out_para.get_rects_for_range(
0..1, 0..1,
@ -133,9 +133,10 @@ fn calculate_cursor_rect(
RectWidthStyle::Tight, RectWidthStyle::Tight,
); );
if !rects.is_empty() { if !rects.is_empty() {
(rects[0].rect.left(), rects[0].rect.height()) let r = &rects[0].rect;
(r.left(), r.top(), r.height())
} else { } else {
(0.0, laid_out_para.height()) (0.0, 0.0, laid_out_para.height())
} }
} else if char_pos >= para_char_count { } else if char_pos >= para_char_count {
let rects = laid_out_para.get_rects_for_range( let rects = laid_out_para.get_rects_for_range(
@ -144,9 +145,10 @@ fn calculate_cursor_rect(
RectWidthStyle::Tight, RectWidthStyle::Tight,
); );
if !rects.is_empty() { if !rects.is_empty() {
(rects[0].rect.right(), rects[0].rect.height()) let r = &rects[0].rect;
(r.right(), r.top(), r.height())
} else { } else {
(laid_out_para.longest_line(), laid_out_para.height()) (laid_out_para.longest_line(), 0.0, laid_out_para.height())
} }
} else { } else {
let rects = laid_out_para.get_rects_for_range( let rects = laid_out_para.get_rects_for_range(
@ -155,17 +157,18 @@ fn calculate_cursor_rect(
RectWidthStyle::Tight, RectWidthStyle::Tight,
); );
if !rects.is_empty() { if !rects.is_empty() {
(rects[0].rect.left(), rects[0].rect.height()) let r = &rects[0].rect;
(r.left(), r.top(), r.height())
} else { } else {
// Fallback: use glyph position // Fallback: use glyph position
let pos = laid_out_para.get_glyph_position_at_coordinate((0.0, 0.0)); let pos = laid_out_para.get_glyph_position_at_coordinate((0.0, 0.0));
(pos.position as f32, laid_out_para.height()) (pos.position as f32, 0.0, laid_out_para.height())
} }
}; };
return Some(Rect::from_xywh( return Some(Rect::from_xywh(
cursor_x, cursor_x,
y_offset, y_offset + cursor_y,
editor_state.theme.cursor_width, editor_state.theme.cursor_width,
cursor_height, cursor_height,
)); ));

View File

@ -480,8 +480,12 @@ impl TextContent {
}; };
if matches { if matches {
// Skia's get_glyph_position_at_coordinate expects coordinates relative to
// the paragraph's top-left. For multi-paragraph or wrapped text, each
// paragraph has its own origin; subtract start_y so we pass paragraph-local coords.
let para_pt = Point::new(point.x, point.y - start_y);
let position_with_affinity = let position_with_affinity =
layout_paragraph.get_glyph_position_at_coordinate(*point); layout_paragraph.get_glyph_position_at_coordinate((para_pt.x, para_pt.y));
if let Some(paragraph) = self.paragraphs().get(paragraph_index) { if let Some(paragraph) = self.paragraphs().get(paragraph_index) {
// Computed position keeps the current position in terms // Computed position keeps the current position in terms
// of number of characters of text. This is used to know // of number of characters of text. This is used to know