Hide the mouse when the user is typing in the editor - take 2 (#27519)

Closes #4461

Take 2 on https://github.com/zed-industries/zed/pull/25040. 

Fixes panic caused due to using `setHiddenUntilMouseMoves` return type
to `set` cursor on macOS.

Release Notes:

- Now cursor hides when the user is typing in editor. It will stay
hidden until it is moved again. This behavior is `true` by default, and
can be configured with `hide_mouse_while_typing` in settings.

---------

Co-authored-by: Peter Tripp <peter@zed.dev>
Co-authored-by: Thomas Mickley-Doyle <thomas@zed.dev>
Co-authored-by: Agus <agus@zed.dev>
Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Agus Zubiaga <hi@aguz.me>
Co-authored-by: Angelk90 <angelo.k90@hotmail.it>
This commit is contained in:
Smit Barmase 2025-03-27 01:58:26 +05:30 committed by GitHub
parent 848a99c605
commit 77856bf017
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
25 changed files with 172 additions and 52 deletions

View file

@ -790,6 +790,8 @@ pub struct Editor {
_scroll_cursor_center_top_bottom_task: Task<()>,
serialize_selections: Task<()>,
serialize_folds: Task<()>,
mouse_cursor_hidden: bool,
hide_mouse_while_typing: bool,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@ -1568,6 +1570,10 @@ impl Editor {
serialize_folds: Task::ready(()),
text_style_refinement: None,
load_diff_task: load_uncommitted_diff,
mouse_cursor_hidden: false,
hide_mouse_while_typing: EditorSettings::get_global(cx)
.hide_mouse_while_typing
.unwrap_or(true),
};
if let Some(breakpoints) = this.breakpoint_store.as_ref() {
this._subscriptions
@ -2999,6 +3005,8 @@ impl Editor {
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
let selections = self.selections.all_adjusted(cx);
let mut bracket_inserted = false;
let mut edits = Vec::new();
@ -3403,6 +3411,7 @@ impl Editor {
}
pub fn newline(&mut self, _: &Newline, window: &mut Window, cx: &mut Context<Self>) {
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.transact(window, cx, |this, window, cx| {
let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
let selections = this.selections.all::<usize>(cx);
@ -3518,6 +3527,8 @@ impl Editor {
}
pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context<Self>) {
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -3575,6 +3586,8 @@ impl Editor {
}
pub fn newline_below(&mut self, _: &NewlineBelow, window: &mut Window, cx: &mut Context<Self>) {
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -7765,6 +7778,7 @@ impl Editor {
}
pub fn backspace(&mut self, _: &Backspace, window: &mut Window, cx: &mut Context<Self>) {
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.transact(window, cx, |this, window, cx| {
this.select_autoclose_pair(window, cx);
let mut linked_ranges = HashMap::<_, Vec<_>>::default();
@ -7863,6 +7877,7 @@ impl Editor {
}
pub fn delete(&mut self, _: &Delete, window: &mut Window, cx: &mut Context<Self>) {
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let line_mode = s.line_mode;
@ -7884,7 +7899,7 @@ impl Editor {
if self.move_to_prev_snippet_tabstop(window, cx) {
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.outdent(&Outdent, window, cx);
}
@ -7892,7 +7907,7 @@ impl Editor {
if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
let mut selections = self.selections.all_adjusted(cx);
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -16669,6 +16684,11 @@ impl Editor {
self.scroll_manager.vertical_scroll_margin = editor_settings.vertical_scroll_margin;
self.show_breadcrumbs = editor_settings.toolbar.breadcrumbs;
self.cursor_shape = editor_settings.cursor_shape.unwrap_or_default();
self.hide_mouse_while_typing = editor_settings.hide_mouse_while_typing.unwrap_or(true);
if !self.hide_mouse_while_typing {
self.mouse_cursor_hidden = false;
}
}
if old_cursor_shape != self.cursor_shape {

View file

@ -39,6 +39,7 @@ pub struct EditorSettings {
#[serde(default)]
pub go_to_definition_fallback: GoToDefinitionFallback,
pub jupyter: Jupyter,
pub hide_mouse_while_typing: Option<bool>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
@ -235,6 +236,10 @@ pub struct EditorSettingsContent {
///
/// Default: None
pub cursor_shape: Option<CursorShape>,
/// Determines whether the mouse cursor should be hidden while typing in an editor or input box.
///
/// Default: true
pub hide_mouse_while_typing: Option<bool>,
/// How to highlight the current line in the editor.
///
/// Default: all

View file

@ -894,6 +894,7 @@ impl EditorElement {
let gutter_hovered = gutter_hitbox.is_hovered(window);
editor.set_gutter_hovered(gutter_hovered, cx);
editor.gutter_breakpoint_indicator = None;
editor.mouse_cursor_hidden = false;
if gutter_hovered {
let new_point = position_map
@ -4307,7 +4308,7 @@ impl EditorElement {
let is_singleton = self.editor.read(cx).is_singleton(cx);
let line_height = layout.position_map.line_height;
window.set_cursor_style(CursorStyle::Arrow, &layout.gutter_hitbox);
window.set_cursor_style(CursorStyle::Arrow, Some(&layout.gutter_hitbox));
for LineNumberLayout {
shaped_line,
@ -4340,9 +4341,9 @@ impl EditorElement {
// In singleton buffers, we select corresponding lines on the line number click, so use | -like cursor.
// In multi buffers, we open file at the line number clicked, so use a pointing hand cursor.
if is_singleton {
window.set_cursor_style(CursorStyle::IBeam, &hitbox);
window.set_cursor_style(CursorStyle::IBeam, Some(&hitbox));
} else {
window.set_cursor_style(CursorStyle::PointingHand, &hitbox);
window.set_cursor_style(CursorStyle::PointingHand, Some(&hitbox));
}
}
}
@ -4564,7 +4565,7 @@ impl EditorElement {
.read(cx)
.all_diff_hunks_expanded()
{
window.set_cursor_style(CursorStyle::PointingHand, hunk_hitbox);
window.set_cursor_style(CursorStyle::PointingHand, Some(hunk_hitbox));
}
}
}
@ -4636,18 +4637,24 @@ impl EditorElement {
bounds: layout.position_map.text_hitbox.bounds,
}),
|window| {
let cursor_style = if self
.editor
.read(cx)
let editor = self.editor.read(cx);
if editor.mouse_cursor_hidden {
window.set_cursor_style(CursorStyle::None, None);
} else if editor
.hovered_link_state
.as_ref()
.is_some_and(|hovered_link_state| !hovered_link_state.links.is_empty())
{
CursorStyle::PointingHand
window.set_cursor_style(
CursorStyle::PointingHand,
Some(&layout.position_map.text_hitbox),
);
} else {
CursorStyle::IBeam
window.set_cursor_style(
CursorStyle::IBeam,
Some(&layout.position_map.text_hitbox),
);
};
window.set_cursor_style(cursor_style, &layout.position_map.text_hitbox);
self.paint_lines_background(layout, window, cx);
let invisible_display_ranges = self.paint_highlights(layout, window);
@ -4842,7 +4849,7 @@ impl EditorElement {
));
})
}
window.set_cursor_style(CursorStyle::Arrow, &hitbox);
window.set_cursor_style(CursorStyle::Arrow, Some(&hitbox));
}
window.on_mouse_event({
@ -6598,6 +6605,7 @@ impl Element for EditorElement {
},
false,
);
// Offset the content_bounds from the text_bounds by the gutter margin (which
// is roughly half a character wide) to make hit testing work more like how we want.
let content_origin =