event_loop, text_edit, layout: focus-time cursor as an end-of-value sentinel, caret height tied to the text line, row align_top/fill_height modes
Focus-time cursor (event_loop/focus.rs): focusing a text input pinned the cursor to a concrete `value.len()` snapshot. When the value keeps growing after focus without the widget seeing keystrokes — crustace's launcher search field is fed over IPC while forge routes the type-to-search keys around Wayland — that snapshot goes stale, and the first key delivered normally afterwards inserts mid-string. The cursor is now seeded with the `usize::MAX` sentinel ("end of whatever value is rendered"), the same convention `select_on_focus` fields already rely on; every consumer (insert/delete, arrow keys, draw, hit-test, context-menu paste offset, a11y tree) clamps via `cursor.min( value.len() )`, so the cursor tracks external growth and collapses to a concrete position on the first real keystroke or click. Click placement is untouched — the pointer path writes its own hit-tested offset.
Caret height (widget/text_edit/draw.rs): the single-line caret spanned `rect.height - 16`, so a field taller than its text line (the launcher's borderless search pill) grew a caret about twice the glyph height. It now measures `font_size + 4`, vertically centered like the text — matching what the multiline caret already did.
Row alignment modes (layout/row.rs): `Row` gains `align_top()` (children pinned to the top edge instead of the default vertical centering) and `fill_height()` (every non-spacer child stretched to the row's inner height, the row itself still sized by its tallest child). Both exist for siblings whose natural heights differ by a few font-metric pixels — like the QS media card next to the wifi/bluetooth chip column — where equal-height layouts cannot be achieved by estimating text heights: `new_line_size` is font-dependent, so px arithmetic in the app always drifts. Containers paint their chrome over the full rect they receive and columns absorb the extra in weighted spacers, so a stretched card keeps its content anchored where its internal spacers put it.
This commit is contained in:
@@ -195,12 +195,16 @@ impl<Msg: Clone> TextEdit<Msg>
|
||||
};
|
||||
let cursor_x = rect.x + theme::PAD_H + align_x - scroll_x
|
||||
+ canvas.measure_text( &cursor_text, font_size );
|
||||
// Caret height follows the text line, not the field box — a
|
||||
// tall field (launcher pill) otherwise grows a caret twice
|
||||
// the glyph height. Matches the multiline caret.
|
||||
let cursor_h = font_size + 4.0;
|
||||
let cursor_rect = Rect
|
||||
{
|
||||
x: cursor_x,
|
||||
y: rect.y + 8.0,
|
||||
y: rect.y + ( rect.height - cursor_h ) / 2.0,
|
||||
width: 2.0,
|
||||
height: rect.height - 16.0,
|
||||
height: cursor_h,
|
||||
};
|
||||
canvas.fill_rect( cursor_rect, theme::cursor(), 0.0 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user