editor: Hide mouse cursor also for movements and selections (#27677)

This enables hiding mouse cursor even on cursor movements like up, down,
etc. or selections made using keyboard, etc.

Renamed existing boolean setting "hide_mouse_while_typing" to
"hide_mouse". It can have three values: `on_typing_and_movement`,
`on_typing`, `never`.

Release Notes:

- Now mouse cursor hides even when you navigate, or make selections
using keyboard in editor. This behavior can be changed by setting
`hide_mouse` to `on_typing_and_movement`, `on_typing` or `never`.
This commit is contained in:
Smit Barmase 2025-03-29 06:53:36 -07:00 committed by GitHub
parent 7fe6188f8e
commit 4970fe2d56
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 264 additions and 44 deletions

View file

@ -164,8 +164,8 @@
//
// Default: not set, defaults to "bar"
"cursor_shape": null,
// Determines whether the mouse cursor is hidden when typing in an editor or input box.
"hide_mouse_while_typing": true,
// Determines when the mouse cursor should be hidden in an editor or input box.
"hide_mouse": "on_typing_and_movement",
// How to highlight the current line in the editor.
//
// 1. Don't highlight the current line:

View file

@ -62,7 +62,8 @@ use display_map::*;
pub use display_map::{DisplayPoint, FoldPlaceholder};
use editor_settings::GoToDefinitionFallback;
pub use editor_settings::{
CurrentLineHighlight, EditorSettings, ScrollBeyondLastLine, SearchSettings, ShowScrollbar,
CurrentLineHighlight, EditorSettings, HideMouseMode, ScrollBeyondLastLine, SearchSettings,
ShowScrollbar,
};
pub use editor_settings_controls::*;
use element::{layout_line, AcceptEditPredictionBinding, LineWithInvisibles, PositionMap};
@ -292,6 +293,11 @@ enum DisplayDiffHunk {
},
}
pub enum HideMouseCursorOrigin {
TypingAction,
MovementAction,
}
pub fn init_settings(cx: &mut App) {
EditorSettings::register(cx);
}
@ -805,7 +811,7 @@ pub struct Editor {
serialize_selections: Task<()>,
serialize_folds: Task<()>,
mouse_cursor_hidden: bool,
hide_mouse_while_typing: bool,
hide_mouse_mode: HideMouseMode,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@ -1586,9 +1592,9 @@ impl Editor {
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),
hide_mouse_mode: EditorSettings::get_global(cx)
.hide_mouse
.unwrap_or_default(),
};
if let Some(breakpoints) = this.breakpoint_store.as_ref() {
this._subscriptions
@ -1722,6 +1728,20 @@ impl Editor {
key_context
}
pub fn hide_mouse_cursor(&mut self, origin: &HideMouseCursorOrigin) {
self.mouse_cursor_hidden = match origin {
HideMouseCursorOrigin::TypingAction => {
matches!(
self.hide_mouse_mode,
HideMouseMode::OnTyping | HideMouseMode::OnTypingAndMovement
)
}
HideMouseCursorOrigin::MovementAction => {
matches!(self.hide_mouse_mode, HideMouseMode::OnTypingAndMovement)
}
};
}
pub fn edit_prediction_in_conflict(&self) -> bool {
if !self.show_edit_predictions_in_menu() {
return false;
@ -3049,7 +3069,7 @@ impl Editor {
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let selections = self.selections.all_adjusted(cx);
let mut bracket_inserted = false;
@ -3455,7 +3475,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.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
let (edits, selection_fixup_info): (Vec<_>, Vec<_>) = {
let selections = this.selections.all::<usize>(cx);
@ -3571,7 +3591,7 @@ 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;
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -3630,7 +3650,7 @@ 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;
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -4493,6 +4513,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.do_completion(action.item_ix, CompletionIntent::Complete, window, cx)
}
@ -4502,6 +4523,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.do_completion(action.item_ix, CompletionIntent::Compose, window, cx)
}
@ -4845,6 +4867,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let actions_menu =
if let CodeContextMenu::CodeActions(menu) = self.hide_context_menu(window, cx)? {
menu
@ -7842,7 +7866,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.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.select_autoclose_pair(window, cx);
let mut linked_ranges = HashMap::<_, Vec<_>>::default();
@ -7941,7 +7965,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.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let line_mode = s.line_mode;
@ -7960,18 +7984,22 @@ impl Editor {
}
pub fn backtab(&mut self, _: &Backtab, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
if self.move_to_prev_snippet_tabstop(window, cx) {
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
self.outdent(&Outdent, window, cx);
}
pub fn tab(&mut self, _: &Tab, window: &mut Window, cx: &mut Context<Self>) {
if self.move_to_next_snippet_tabstop(window, cx) || self.read_only(cx) {
if self.move_to_next_snippet_tabstop(window, cx) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
return;
}
self.mouse_cursor_hidden = self.hide_mouse_while_typing;
if self.read_only(cx) {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let mut selections = self.selections.all_adjusted(cx);
let buffer = self.buffer.read(cx);
let snapshot = buffer.snapshot(cx);
@ -8052,6 +8080,7 @@ impl Editor {
if self.read_only(cx) {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let mut selections = self.selections.all::<Point>(cx);
let mut prev_edited_row = 0;
let mut row_delta = 0;
@ -8156,6 +8185,7 @@ impl Editor {
if self.read_only(cx) {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all::<Point>(cx);
let mut deletion_ranges = Vec::new();
@ -8229,6 +8259,7 @@ impl Editor {
if self.read_only(cx) {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let selections = self
.selections
.all::<usize>(cx)
@ -8247,6 +8278,7 @@ impl Editor {
}
pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let selections = self.selections.all::<Point>(cx);
@ -8395,6 +8427,7 @@ impl Editor {
}
pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.join_lines_impl(true, window, cx);
}
@ -8456,6 +8489,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let mut buffer_ids = HashSet::default();
let snapshot = self.buffer().read(cx).snapshot(cx);
for selection in self.selections.all::<usize>(cx) {
@ -8472,6 +8506,7 @@ impl Editor {
}
pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let selections = self
.selections
.all(cx)
@ -8854,6 +8889,8 @@ impl Editor {
) where
Fn: FnMut(&mut Vec<&str>),
{
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = self.buffer.read(cx).snapshot(cx);
@ -9092,6 +9129,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = &display_map.buffer_snapshot;
let selections = self.selections.all::<Point>(cx);
@ -9176,6 +9215,8 @@ impl Editor {
}
pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = self.buffer.read(cx).snapshot(cx);
@ -9281,6 +9322,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = self.buffer.read(cx).snapshot(cx);
@ -9371,6 +9414,7 @@ impl Editor {
}
pub fn transpose(&mut self, _: &Transpose, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let text_layout_details = &self.text_layout_details(window);
self.transact(window, cx, |this, window, cx| {
let edits = this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -9429,6 +9473,7 @@ impl Editor {
}
pub fn rewrap(&mut self, _: &Rewrap, _: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.rewrap_impl(RewrapOptions::default(), cx)
}
@ -9644,11 +9689,13 @@ impl Editor {
}
pub fn cut(&mut self, _: &Cut, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let item = self.cut_common(window, cx);
cx.write_to_clipboard(item);
}
pub fn kill_ring_cut(&mut self, _: &KillRingCut, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.change_selections(None, window, cx, |s| {
s.move_with(|snapshot, sel| {
if sel.is_empty() {
@ -9666,6 +9713,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let (text, metadata) = if let Some(KillRing(item)) = cx.try_global() {
if let Some(ClipboardEntry::String(kill_ring)) = item.entries().first() {
(kill_ring.text().to_string(), kill_ring.metadata_json())
@ -9854,6 +9902,7 @@ impl Editor {
}
pub fn paste(&mut self, _: &Paste, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
if let Some(item) = cx.read_from_clipboard() {
let entries = item.entries();
@ -9878,6 +9927,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
if let Some((selections, _)) =
self.selection_history.transaction(transaction_id).cloned()
@ -9906,6 +9957,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
if let Some(transaction_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
if let Some((_, Some(selections))) =
self.selection_history.transaction(transaction_id).cloned()
@ -9939,6 +9992,7 @@ impl Editor {
}
pub fn move_left(&mut self, _: &MoveLeft, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let line_mode = s.line_mode;
s.move_with(|map, selection| {
@ -9953,12 +10007,14 @@ impl Editor {
}
pub fn select_left(&mut self, _: &SelectLeft, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| (movement::left(map, head), SelectionGoal::None));
})
}
pub fn move_right(&mut self, _: &MoveRight, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let line_mode = s.line_mode;
s.move_with(|map, selection| {
@ -9973,6 +10029,7 @@ impl Editor {
}
pub fn select_right(&mut self, _: &SelectRight, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| (movement::right(map, head), SelectionGoal::None));
})
@ -9988,6 +10045,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
let selection_count = self.selections.count();
let first_selection = self.selections.first_anchor();
@ -10030,6 +10089,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10066,6 +10127,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10093,6 +10156,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, goal| {
@ -10107,6 +10171,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, goal| {
@ -10125,6 +10190,8 @@ impl Editor {
return;
};
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10163,6 +10230,8 @@ impl Editor {
return;
};
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let autoscroll = if action.center_cursor {
Autoscroll::center()
} else {
@ -10191,6 +10260,7 @@ impl Editor {
}
pub fn select_up(&mut self, _: &SelectUp, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, goal| {
@ -10207,6 +10277,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
let selection_count = self.selections.count();
let first_selection = self.selections.first_anchor();
@ -10244,6 +10316,8 @@ impl Editor {
return;
};
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10282,6 +10356,8 @@ impl Editor {
return;
};
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let autoscroll = if action.center_cursor {
Autoscroll::center()
} else {
@ -10309,6 +10385,7 @@ impl Editor {
}
pub fn select_down(&mut self, _: &SelectDown, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let text_layout_details = &self.text_layout_details(window);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, goal| {
@ -10367,6 +10444,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(
@ -10383,6 +10461,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(
@ -10399,6 +10478,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10415,6 +10495,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10431,6 +10512,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.select_autoclose_pair(window, cx);
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10456,6 +10538,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.select_autoclose_pair(window, cx);
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
@ -10477,6 +10560,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(movement::next_word_end(map, head), SelectionGoal::None)
@ -10490,6 +10574,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(movement::next_subword_end(map, head), SelectionGoal::None)
@ -10503,6 +10588,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(movement::next_word_end(map, head), SelectionGoal::None)
@ -10516,6 +10602,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(movement::next_subword_end(map, head), SelectionGoal::None)
@ -10529,6 +10616,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
let line_mode = s.line_mode;
@ -10553,6 +10641,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
@ -10572,6 +10661,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(
@ -10593,6 +10683,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10614,6 +10705,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|_, selection| {
@ -10639,6 +10731,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_cursors_with(|map, head, _| {
(
@ -10655,6 +10748,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10671,6 +10765,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.select_to_end_of_line(
&SelectToEndOfLine {
@ -10689,6 +10784,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
this.select_to_end_of_line(
&SelectToEndOfLine {
@ -10711,7 +10807,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
selection.collapse_to(
@ -10732,7 +10828,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
selection.collapse_to(
@ -10753,7 +10849,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10774,7 +10870,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10795,7 +10891,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
selection.collapse_to(
@ -10845,7 +10941,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
selection.collapse_to(
@ -10870,7 +10966,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_with(|map, selection| {
selection.collapse_to(
@ -10895,7 +10991,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10916,7 +11012,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10937,7 +11033,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10958,7 +11054,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_heads_with(|map, head, _| {
(
@ -10979,7 +11075,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(vec![0..0]);
});
@ -10993,7 +11089,7 @@ impl Editor {
) {
let mut selection = self.selections.last::<Point>(cx);
selection.set_head(Point::zero(), SelectionGoal::None);
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select(vec![selection]);
});
@ -11004,7 +11100,7 @@ impl Editor {
cx.propagate();
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let cursor = self.buffer.read(cx).read(cx).len();
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.select_ranges(vec![cursor..cursor])
@ -11061,6 +11157,7 @@ impl Editor {
}
pub fn select_to_end(&mut self, _: &SelectToEnd, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let buffer = self.buffer.read(cx).snapshot(cx);
let mut selection = self.selections.first::<usize>(cx);
selection.set_head(buffer.len(), SelectionGoal::None);
@ -11070,6 +11167,7 @@ impl Editor {
}
pub fn select_all(&mut self, _: &SelectAll, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let end = self.buffer.read(cx).read(cx).len();
self.change_selections(None, window, cx, |s| {
s.select_ranges(vec![0..end]);
@ -11077,6 +11175,7 @@ impl Editor {
}
pub fn select_line(&mut self, _: &SelectLine, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let mut selections = self.selections.all::<Point>(cx);
let max_point = display_map.buffer_snapshot.max_point();
@ -11147,6 +11246,8 @@ impl Editor {
}
fn add_selection(&mut self, above: bool, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let mut selections = self.selections.all::<Point>(cx);
let text_layout_details = self.text_layout_details(window);
@ -11427,6 +11528,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.push_to_selection_history();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
@ -11512,6 +11615,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.push_to_selection_history();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
self.select_next_match_internal(
@ -11530,6 +11634,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Result<()> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.push_to_selection_history();
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = &display_map.buffer_snapshot;
@ -11676,6 +11781,7 @@ impl Editor {
if self.read_only(cx) {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let text_layout_details = &self.text_layout_details(window);
self.transact(window, cx, |this, window, cx| {
let mut selections = this.selections.all::<MultiBufferPoint>(cx);
@ -11975,6 +12081,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let buffer = self.buffer.read(cx).snapshot(cx);
let old_selections = self.selections.all::<usize>(cx).into_boxed_slice();
@ -12036,6 +12144,8 @@ impl Editor {
return;
}
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
let buffer = self.buffer.read(cx).snapshot(cx);
@ -12144,6 +12254,8 @@ impl Editor {
return;
};
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
if let Some((mut selections, scroll_behavior, is_selection_reversed)) =
self.select_syntax_node_history.pop()
{
@ -12337,6 +12449,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
s.move_offsets_with(|snapshot, selection| {
let Some(enclosing_bracket_ranges) =
@ -12397,6 +12510,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.end_selection(window, cx);
self.selection_history.mode = SelectionHistoryMode::Undoing;
if let Some(entry) = self.selection_history.undo_stack.pop_back() {
@ -12417,6 +12531,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.end_selection(window, cx);
self.selection_history.mode = SelectionHistoryMode::Redoing;
if let Some(entry) = self.selection_history.redo_stack.pop_back() {
@ -12539,6 +12654,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.go_to_diagnostic_impl(Direction::Next, window, cx)
}
@ -12548,6 +12664,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
self.go_to_diagnostic_impl(Direction::Prev, window, cx)
}
@ -12694,6 +12811,7 @@ impl Editor {
}
fn go_to_next_hunk(&mut self, _: &GoToHunk, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let snapshot = self.snapshot(window, cx);
let selection = self.selections.newest::<Point>(cx);
self.go_to_hunk_before_or_after_position(
@ -12754,6 +12872,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction);
let snapshot = self.snapshot(window, cx);
let selection = self.selections.newest::<Point>(cx);
self.go_to_hunk_before_or_after_position(
@ -13238,6 +13357,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<Navigated>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let selection = self.selections.newest::<usize>(cx);
let multi_buffer = self.buffer.read(cx);
let head = selection.head();
@ -13712,6 +13833,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let project = match &self.project {
Some(project) => project.clone(),
None => return None,
@ -13732,6 +13855,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let project = match &self.project {
Some(project) => project.clone(),
None => return None,
@ -13829,6 +13954,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) -> Option<Task<Result<()>>> {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let project = match &self.project {
Some(project) => project.clone(),
None => return None,
@ -15073,6 +15199,8 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let buffers = self.buffer.read(cx).all_buffers();
for branch_buffer in buffers {
branch_buffer.update(cx, |branch_buffer, cx| {
@ -15091,6 +15219,7 @@ impl Editor {
window: &mut Window,
cx: &mut Context<Self>,
) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
let snapshot = self.snapshot(window, cx);
let hunks = snapshot.hunks_for_ranges(self.selections.ranges(cx));
let mut ranges_by_buffer = HashMap::default();
@ -15964,6 +16093,7 @@ impl Editor {
}
fn insert_uuid(&mut self, version: UuidVersion, window: &mut Window, cx: &mut Context<Self>) {
self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction);
self.transact(window, cx, |this, window, cx| {
let edits = this
.selections
@ -16757,11 +16887,7 @@ 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;
}
self.hide_mouse_mode = editor_settings.hide_mouse.unwrap_or_default();
}
if old_cursor_shape != self.cursor_shape {

View file

@ -39,7 +39,7 @@ pub struct EditorSettings {
#[serde(default)]
pub go_to_definition_fallback: GoToDefinitionFallback,
pub jupyter: Jupyter,
pub hide_mouse_while_typing: Option<bool>,
pub hide_mouse: Option<HideMouseMode>,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
@ -225,6 +225,21 @@ pub enum GoToDefinitionFallback {
FindAllReferences,
}
/// Determines when the mouse cursor should be hidden in an editor or input box.
///
/// Default: on_typing_and_movement
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HideMouseMode {
/// Never hide the mouse cursor
Never,
/// Hide only when typing
OnTyping,
/// Hide on both typing and cursor movement
#[default]
OnTypingAndMovement,
}
#[derive(Clone, Default, Serialize, Deserialize, JsonSchema)]
pub struct EditorSettingsContent {
/// Whether the cursor blinks in the editor.
@ -236,10 +251,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.
/// Determines when the mouse cursor should be hidden in an editor or input box.
///
/// Default: true
pub hide_mouse_while_typing: Option<bool>,
/// Default: on_typing_and_movement
pub hide_mouse: Option<HideMouseMode>,
/// How to highlight the current line in the editor.
///
/// Default: all

View file

@ -31,3 +31,9 @@ pub(crate) mod m_2025_03_06 {
pub(crate) use keymap::KEYMAP_PATTERNS;
}
pub(crate) mod m_2025_03_29 {
mod settings;
pub(crate) use settings::SETTINGS_PATTERNS;
}

View file

@ -0,0 +1,65 @@
use std::ops::Range;
use tree_sitter::{Query, QueryMatch};
use crate::patterns::SETTINGS_ROOT_KEY_VALUE_PATTERN;
use crate::MigrationPatterns;
pub const SETTINGS_PATTERNS: MigrationPatterns = &[
(SETTINGS_ROOT_KEY_VALUE_PATTERN, replace_setting_name),
(SETTINGS_ROOT_KEY_VALUE_PATTERN, replace_setting_value),
];
fn replace_setting_value(
contents: &str,
mat: &QueryMatch,
query: &Query,
) -> Option<(Range<usize>, String)> {
let setting_capture_ix = query.capture_index_for_name("name")?;
let setting_name_range = mat
.nodes_for_capture_index(setting_capture_ix)
.next()?
.byte_range();
let setting_name = contents.get(setting_name_range.clone())?;
if setting_name != "hide_mouse_while_typing" {
return None;
}
let value_capture_ix = query.capture_index_for_name("value")?;
let value_range = mat
.nodes_for_capture_index(value_capture_ix)
.next()?
.byte_range();
let value = contents.get(value_range.clone())?;
let new_value = if value.trim() == "true" {
"\"on_typing_and_movement\""
} else if value.trim() == "false" {
"\"never\""
} else {
return None;
};
Some((value_range, new_value.to_string()))
}
fn replace_setting_name(
contents: &str,
mat: &QueryMatch,
query: &Query,
) -> Option<(Range<usize>, String)> {
let setting_capture_ix = query.capture_index_for_name("name")?;
let setting_name_range = mat
.nodes_for_capture_index(setting_capture_ix)
.next()?
.byte_range();
let setting_name = contents.get(setting_name_range.clone())?;
let new_setting_name = if setting_name == "hide_mouse_while_typing" {
"hide_mouse"
} else {
return None;
};
Some((setting_name_range, new_setting_name.to_string()))
}

View file

@ -116,6 +116,10 @@ pub fn migrate_settings(text: &str) -> Result<Option<String>> {
migrations::m_2025_01_30::SETTINGS_PATTERNS,
&SETTINGS_QUERY_2025_01_30,
),
(
migrations::m_2025_03_29::SETTINGS_PATTERNS,
&SETTINGS_QUERY_2025_03_29,
),
];
run_migrations(text, migrations)
}
@ -182,6 +186,10 @@ define_query!(
SETTINGS_QUERY_2025_01_30,
migrations::m_2025_01_30::SETTINGS_PATTERNS
);
define_query!(
SETTINGS_QUERY_2025_03_29,
migrations::m_2025_03_29::SETTINGS_PATTERNS
);
// custom query
static EDIT_PREDICTION_SETTINGS_MIGRATION_QUERY: LazyLock<Query> = LazyLock::new(|| {

View file

@ -2,7 +2,7 @@ pub const SETTINGS_ROOT_KEY_VALUE_PATTERN: &str = r#"(document
(object
(pair
key: (string (string_content) @name)
value: (_)
value: (_) @value
)
)
)"#;

View file

@ -553,11 +553,11 @@ List of `string` values
"cursor_shape": "hollow"
```
## Hide Mouse While Typing
## Hide Mouse
- Description: Determines whether the mouse cursor should be hidden while typing in an editor or input box.
- Setting: `hide_mouse_while_typing`
- Default: `true`
- Description: Determines when the mouse cursor should be hidden in an editor or input box.
- Setting: `hide_mouse`
- Default: `on_typing_and_movement`
**Options**