diff --git a/assets/settings/default.json b/assets/settings/default.json index 23ce584c96..946c1847b5 100644 --- a/assets/settings/default.json +++ b/assets/settings/default.json @@ -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: diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a2b720a4b1..85eb34416c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -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.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::(cx); @@ -3571,7 +3591,7 @@ impl Editor { } pub fn newline_above(&mut self, _: &NewlineAbove, window: &mut Window, cx: &mut Context) { - 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.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, ) -> Option>> { + 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, ) -> Option>> { + 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, ) -> Option>> { + 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.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.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.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) { - 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::(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::(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::(cx) @@ -8247,6 +8278,7 @@ impl Editor { } pub fn delete_line(&mut self, _: &DeleteLine, window: &mut Window, cx: &mut Context) { + self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let selections = self.selections.all::(cx); @@ -8395,6 +8427,7 @@ impl Editor { } pub fn join_lines(&mut self, _: &JoinLines, window: &mut Window, cx: &mut Context) { + 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.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::(cx) { @@ -8472,6 +8506,7 @@ impl Editor { } pub fn git_restore(&mut self, _: &Restore, window: &mut Window, cx: &mut Context) { + 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.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::(cx); @@ -9176,6 +9215,8 @@ impl Editor { } pub fn move_line_up(&mut self, _: &MoveLineUp, window: &mut Window, cx: &mut Context) { + 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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::(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.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); let buffer = self.buffer.read(cx).snapshot(cx); let mut selection = self.selections.first::(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.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.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let mut selections = self.selections.all::(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.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); + let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx)); let mut selections = self.selections.all::(cx); let text_layout_details = self.text_layout_details(window); @@ -11427,6 +11528,8 @@ impl Editor { window: &mut Window, cx: &mut Context, ) -> 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, ) -> 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, ) -> 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::(cx); @@ -11975,6 +12081,8 @@ impl Editor { window: &mut Window, cx: &mut Context, ) { + self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); + let buffer = self.buffer.read(cx).snapshot(cx); let old_selections = self.selections.all::(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.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.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.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.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.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.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); let snapshot = self.snapshot(window, cx); let selection = self.selections.newest::(cx); self.go_to_hunk_before_or_after_position( @@ -12754,6 +12872,7 @@ impl Editor { window: &mut Window, cx: &mut Context, ) { + self.hide_mouse_cursor(&HideMouseCursorOrigin::MovementAction); let snapshot = self.snapshot(window, cx); let selection = self.selections.newest::(cx); self.go_to_hunk_before_or_after_position( @@ -13238,6 +13357,8 @@ impl Editor { window: &mut Window, cx: &mut Context, ) -> Option>> { + self.hide_mouse_cursor(&HideMouseCursorOrigin::TypingAction); + let selection = self.selections.newest::(cx); let multi_buffer = self.buffer.read(cx); let head = selection.head(); @@ -13712,6 +13833,8 @@ impl Editor { window: &mut Window, cx: &mut Context, ) -> Option>> { + 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, ) -> Option>> { + 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, ) -> Option>> { + 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.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.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.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 { diff --git a/crates/editor/src/editor_settings.rs b/crates/editor/src/editor_settings.rs index 30c1eae5fb..5622c0c398 100644 --- a/crates/editor/src/editor_settings.rs +++ b/crates/editor/src/editor_settings.rs @@ -39,7 +39,7 @@ pub struct EditorSettings { #[serde(default)] pub go_to_definition_fallback: GoToDefinitionFallback, pub jupyter: Jupyter, - pub hide_mouse_while_typing: Option, + pub hide_mouse: Option, } #[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, - /// 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, + /// Default: on_typing_and_movement + pub hide_mouse: Option, /// How to highlight the current line in the editor. /// /// Default: all diff --git a/crates/migrator/src/migrations.rs b/crates/migrator/src/migrations.rs index e4b9894ae0..a0a070051c 100644 --- a/crates/migrator/src/migrations.rs +++ b/crates/migrator/src/migrations.rs @@ -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; +} diff --git a/crates/migrator/src/migrations/m_2025_03_29/settings.rs b/crates/migrator/src/migrations/m_2025_03_29/settings.rs new file mode 100644 index 0000000000..367929c713 --- /dev/null +++ b/crates/migrator/src/migrations/m_2025_03_29/settings.rs @@ -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, 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, 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())) +} diff --git a/crates/migrator/src/migrator.rs b/crates/migrator/src/migrator.rs index 75b471bad6..8c1227c58a 100644 --- a/crates/migrator/src/migrator.rs +++ b/crates/migrator/src/migrator.rs @@ -116,6 +116,10 @@ pub fn migrate_settings(text: &str) -> Result> { 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 = LazyLock::new(|| { diff --git a/crates/migrator/src/patterns/settings.rs b/crates/migrator/src/patterns/settings.rs index 107b781699..e8624c7f9f 100644 --- a/crates/migrator/src/patterns/settings.rs +++ b/crates/migrator/src/patterns/settings.rs @@ -2,7 +2,7 @@ pub const SETTINGS_ROOT_KEY_VALUE_PATTERN: &str = r#"(document (object (pair key: (string (string_content) @name) - value: (_) + value: (_) @value ) ) )"#; diff --git a/docs/src/configuring-zed.md b/docs/src/configuring-zed.md index 2e700b988d..e77615c12b 100644 --- a/docs/src/configuring-zed.md +++ b/docs/src/configuring-zed.md @@ -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**