🎉 Add LTR/RTL cursor navigation

This commit is contained in:
Aitor Moreno
2026-03-04 12:10:23 +01:00
parent 5a1461a910
commit 920e66fd24
2 changed files with 38 additions and 6 deletions

View File

@@ -204,10 +204,6 @@ impl TextEditorState {
content: &TextContent,
position: &TextPositionWithAffinity,
) {
fn is_word_char(c: char) -> bool {
c.is_alphanumeric() || c == '_'
}
self.is_pointer_selection_active = false;
let paragraphs = content.paragraphs();
@@ -320,3 +316,7 @@ impl TextEditorState {
!self.pending_events.is_empty()
}
}
fn is_word_char(c: char) -> bool {
c.is_alphanumeric() || c == '_'
}

View File

@@ -7,7 +7,7 @@ use crate::state::TextSelection;
use crate::utils::uuid_from_u32_quartet;
use crate::utils::uuid_to_u32_quartet;
use crate::{with_state, with_state_mut, STATE};
use skia_safe::Color;
use skia_safe::{textlayout::TextDirection, Color};
#[derive(PartialEq, ToJs)]
#[repr(u8)]
@@ -527,7 +527,25 @@ pub extern "C" fn text_editor_move_cursor(direction: CursorDirection, extend_sel
let current = state.text_editor_state.selection.focus;
let new_cursor = match direction {
// Get the text direction of the span at the current cursor position
let span_text_direction = if current.paragraph < paragraphs.len() {
get_span_text_direction_at_offset(&paragraphs[current.paragraph], current.offset)
} else {
TextDirection::LTR
};
// For horizontal navigation, swap Backward/Forward when in RTL text
let adjusted_direction = if span_text_direction == TextDirection::RTL {
match direction {
CursorDirection::Backward => CursorDirection::Forward,
CursorDirection::Forward => CursorDirection::Backward,
other => other,
}
} else {
direction
};
let new_cursor = match adjusted_direction {
CursorDirection::Backward => move_cursor_backward(&current, paragraphs),
CursorDirection::Forward => move_cursor_forward(&current, paragraphs),
CursorDirection::LineBefore => {
@@ -1136,6 +1154,20 @@ fn insert_text_with_newlines(
Some(current_cursor)
}
/// Get the text direction of the span at a given offset in a paragraph.
fn get_span_text_direction_at_offset(
para: &Paragraph,
char_offset: usize,
) -> skia_safe::textlayout::TextDirection {
if let Some((span_idx, _)) = find_span_at_offset(para, char_offset) {
if let Some(span) = para.children().get(span_idx) {
return span.text_direction;
}
}
// Fallback to paragraph's text direction
para.text_direction()
}
/// Insert text at a cursor position. Returns the new character offset after insertion.
fn insert_text_at_cursor(
text_content: &mut TextContent,