rework InputState::cursor_visible to be more clear that its a mutation during paint

This commit is contained in:
temportalflux
2026-07-11 09:31:07 -04:00
parent 890a0e6daf
commit 4037fc5a92
2 changed files with 29 additions and 24 deletions
+4 -5
View File
@@ -139,10 +139,9 @@ impl Element for Input {
let is_focused = focus_handle.is_focused(window);
let colors = self.colors;
// TODO: refactor cursor_visible so it is clear that it is called on_paint
let cursor_visible = self
.input
.update(cx, |input, cx| input.cursor_visible(is_focused, cx));
let is_cursor_visible = self.input.update(cx, |input, cx| {
input.toggle_cursor_on_focus_change(is_focused, cx)
});
let perform_paint = |_style: &Style, window: &mut Window, cx: &mut App| {
let precomputed_first_line = match (snapshot.layout, snapshot.line_layouts.first()) {
@@ -166,7 +165,7 @@ impl Element for Input {
text_style: &text_style,
placeholder: placeholder.as_ref(),
colors: &colors,
cursor_visible,
cursor_visible: is_cursor_visible,
precomputed_first_line,
};
context.process_mouse_events(&self.input, window, cx);
+25 -19
View File
@@ -1,5 +1,5 @@
use super::actions::*;
use crate::input::{InputLayout, unicode::UnicodeString};
use crate::input::{CursorBlink, InputLayout, unicode::UnicodeString};
use gpui::{
App, AppContext, ClipboardItem, Context, Entity, EntityId, EntityInputHandler, EventEmitter,
FocusHandle, Focusable, Pixels, Point, SharedString, Subscription, TextRun, TextStyle, Window,
@@ -151,27 +151,33 @@ impl InputState {
self
}
/// Returns whether the cursor should be visible (for blinking).
///
/// If blinking is not enabled, always returns `true`.
/// This method also updates the blink manager's enabled state based on focus.
pub fn cursor_visible(&mut self, is_focused: bool, cx: &mut Context<Self>) -> bool {
/// Processes a focus-flag update during window paint, returning whether the cursor should be visible in this frame.
/// Returns false if the cursor is blinking and not currently visible.
pub(super) fn toggle_cursor_on_focus_change(
&mut self,
is_focused: bool,
cx: &mut Context<Self>,
) -> bool {
// Update cursor blink based on focus changes
if let Some((cursor_blink, _)) = &self.cursor_blink {
if is_focused && !self.was_focused {
cursor_blink.update(cx, |cb, cx| cb.enable(cx));
cx.emit(InputStateEvent::Focus);
} else if !is_focused && self.was_focused {
cursor_blink.update(cx, |cb, cx| cb.disable(cx));
cx.emit(InputStateEvent::Blur);
}
}
let was_focused = self.was_focused;
self.was_focused = is_focused;
self.cursor_blink
.as_ref()
.map(|(cb, _)| cb.read(cx).visible())
.unwrap_or(true)
match &self.cursor_blink {
None => true,
Some((cursor_blink, _)) => match (is_focused, was_focused) {
(true, false) => {
cursor_blink.update(cx, |cursor, cx| cursor.enable(cx));
cx.emit(InputStateEvent::Focus);
true
}
(false, true) => {
cursor_blink.update(cx, |cursor, cx| cursor.disable(cx));
cx.emit(InputStateEvent::Blur);
false
}
_ => cursor_blink.read(cx).visible(),
},
}
}
/// Pauses cursor blinking temporarily (e.g., during typing).