Revert "Hide the mouse when the user is typing in the editor (#25040)" (#25393)

Marshall Bowers created

This reverts commit a8610fbd13a5999149a426ed169f2c322f8e54bd.

I've been seeing some reports of segmentation faults that appear to
point to this change as the culprit.

Closes #25366.

Release Notes:

- Community: Reverted #25040, so remove the corresponding entry from the
release notes.

Change summary

assets/settings/default.json                     |  2 -
crates/editor/src/editor.rs                      | 13 --------
crates/editor/src/editor_settings.rs             |  5 ---
crates/editor/src/element.rs                     |  9 +---
crates/gpui/src/platform.rs                      |  3 -
crates/gpui/src/platform/linux/platform.rs       |  6 ---
crates/gpui/src/platform/linux/wayland.rs        |  6 ---
crates/gpui/src/platform/linux/wayland/client.rs |  8 ----
crates/gpui/src/platform/linux/x11/client.rs     | 29 +++--------------
crates/gpui/src/platform/mac/platform.rs         |  1 
crates/gpui/src/platform/windows/events.rs       | 18 +---------
crates/gpui/src/platform/windows/platform.rs     |  8 ++--
crates/gpui/src/platform/windows/util.rs         | 23 ++++++--------
crates/gpui/src/platform/windows/window.rs       |  6 +-
crates/gpui/src/window.rs                        |  1 
crates/gpui_macros/src/styles.rs                 |  7 ----
docs/src/configuring-zed.md                      | 10 ------
17 files changed, 28 insertions(+), 127 deletions(-)

Detailed changes

assets/settings/default.json 🔗

@@ -150,8 +150,6 @@
   //
   // 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,
   // How to highlight the current line in the editor.
   //
   // 1. Don't highlight the current line:

crates/editor/src/editor.rs 🔗

@@ -729,8 +729,6 @@ pub struct Editor {
     toggle_fold_multiple_buffers: Task<()>,
     _scroll_cursor_center_top_bottom_task: Task<()>,
     serialize_selections: Task<()>,
-    mouse_cursor_hidden: bool,
-    hide_mouse_while_typing: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@@ -1454,10 +1452,6 @@ impl Editor {
             serialize_selections: 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),
         };
         this.tasks_update_task = Some(this.refresh_runnables(window, cx));
         this._subscriptions.extend(project_subscriptions);
@@ -2795,8 +2789,6 @@ 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();
@@ -14611,11 +14603,6 @@ 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 {

crates/editor/src/editor_settings.rs 🔗

@@ -37,7 +37,6 @@ pub struct EditorSettings {
     pub auto_signature_help: bool,
     pub show_signature_help_after_edits: bool,
     pub jupyter: Jupyter,
-    pub hide_mouse_while_typing: Option<bool>,
 }
 
 #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq, JsonSchema)]
@@ -271,10 +270,6 @@ 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

crates/editor/src/element.rs 🔗

@@ -853,7 +853,6 @@ impl EditorElement {
         let modifiers = event.modifiers;
         let gutter_hovered = gutter_hitbox.is_hovered(window);
         editor.set_gutter_hovered(gutter_hovered, cx);
-        editor.mouse_cursor_hidden = false;
 
         // Don't trigger hover popover if mouse is hovering over context menu
         if text_hitbox.is_hovered(window) {
@@ -4969,10 +4968,9 @@ impl EditorElement {
                 bounds: layout.position_map.text_hitbox.bounds,
             }),
             |window| {
-                let editor = self.editor.read(cx);
-                let cursor_style = if editor.mouse_cursor_hidden {
-                    CursorStyle::None
-                } else if editor
+                let cursor_style = if self
+                    .editor
+                    .read(cx)
                     .hovered_link_state
                     .as_ref()
                     .is_some_and(|hovered_link_state| !hovered_link_state.links.is_empty())
@@ -6984,7 +6982,6 @@ 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 =

crates/gpui/src/platform.rs 🔗

@@ -1227,9 +1227,6 @@ pub enum CursorStyle {
     /// A cursor indicating that the operation will result in a context menu
     /// corresponds to the CSS cursor value `context-menu`
     ContextualMenu,
-
-    /// Hide the cursor
-    None,
 }
 
 impl Default for CursorStyle {

crates/gpui/src/platform/linux/platform.rs 🔗

@@ -666,12 +666,6 @@ impl CursorStyle {
             CursorStyle::DragLink => "alias",
             CursorStyle::DragCopy => "copy",
             CursorStyle::ContextualMenu => "context-menu",
-            CursorStyle::None => {
-                #[cfg(debug_assertions)]
-                panic!("CursorStyle::None should be handled separately in the client");
-                #[cfg(not(debug_assertions))]
-                "default"
-            }
         }
         .to_string()
     }

crates/gpui/src/platform/linux/wayland.rs 🔗

@@ -35,12 +35,6 @@ impl CursorStyle {
             CursorStyle::DragLink => Shape::Alias,
             CursorStyle::DragCopy => Shape::Copy,
             CursorStyle::ContextualMenu => Shape::ContextMenu,
-            CursorStyle::None => {
-                #[cfg(debug_assertions)]
-                panic!("CursorStyle::None should be handled separately in the client");
-                #[cfg(not(debug_assertions))]
-                Shape::Default
-            }
         }
     }
 }

crates/gpui/src/platform/linux/wayland/client.rs 🔗

@@ -667,13 +667,7 @@ impl LinuxClient for WaylandClient {
             let serial = state.serial_tracker.get(SerialKind::MouseEnter);
             state.cursor_style = Some(style);
 
-            if let CursorStyle::None = style {
-                let wl_pointer = state
-                    .wl_pointer
-                    .clone()
-                    .expect("window is focused by pointer");
-                wl_pointer.set_cursor(serial, None, 0, 0);
-            } else if let Some(cursor_shape_device) = &state.cursor_shape_device {
+            if let Some(cursor_shape_device) = &state.cursor_shape_device {
                 cursor_shape_device.set_shape(serial, style.to_shape());
             } else if let Some(focused_window) = &state.mouse_focused_window {
                 // cursor-shape-v1 isn't supported, set the cursor using a surface.

crates/gpui/src/platform/linux/x11/client.rs 🔗

@@ -1438,16 +1438,13 @@ impl LinuxClient for X11Client {
         let cursor = match state.cursor_cache.get(&style) {
             Some(cursor) => *cursor,
             None => {
-                let Some(cursor) = (match style {
-                    CursorStyle::None => create_invisible_cursor(&state.xcb_connection).log_err(),
-                    _ => state
-                        .cursor_handle
-                        .load_cursor(&state.xcb_connection, &style.to_icon_name())
-                        .log_err(),
-                }) else {
+                let Some(cursor) = state
+                    .cursor_handle
+                    .load_cursor(&state.xcb_connection, &style.to_icon_name())
+                    .log_err()
+                else {
                     return;
                 };
-
                 state.cursor_cache.insert(style, cursor);
                 cursor
             }
@@ -1941,19 +1938,3 @@ fn make_scroll_wheel_event(
         touch_phase: TouchPhase::default(),
     }
 }
-
-fn create_invisible_cursor(
-    connection: &XCBConnection,
-) -> anyhow::Result<crate::platform::linux::x11::client::xproto::Cursor> {
-    let empty_pixmap = connection.generate_id()?;
-    let root = connection.setup().roots[0].root;
-    connection.create_pixmap(1, empty_pixmap, root, 1, 1)?;
-
-    let cursor = connection.generate_id()?;
-    connection.create_cursor(cursor, empty_pixmap, empty_pixmap, 0, 0, 0, 0, 0, 0, 0, 0)?;
-
-    connection.free_pixmap(empty_pixmap)?;
-
-    connection.flush()?;
-    Ok(cursor)
-}

crates/gpui/src/platform/mac/platform.rs 🔗

@@ -938,7 +938,6 @@ impl Platform for MacPlatform {
                 CursorStyle::DragLink => msg_send![class!(NSCursor), dragLinkCursor],
                 CursorStyle::DragCopy => msg_send![class!(NSCursor), dragCopyCursor],
                 CursorStyle::ContextualMenu => msg_send![class!(NSCursor), contextualMenuCursor],
-                CursorStyle::None => msg_send![class!(NSCursor), setHiddenUntilMouseMoves:YES],
             };
 
             let old_cursor: id = msg_send![class!(NSCursor), currentCursor];

crates/gpui/src/platform/windows/events.rs 🔗

@@ -1121,19 +1121,7 @@ fn handle_nc_mouse_up_msg(
 }
 
 fn handle_cursor_changed(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Option<isize> {
-    let mut state = state_ptr.state.borrow_mut();
-    let had_cursor = state.current_cursor.is_some();
-
-    state.current_cursor = if lparam.0 == 0 {
-        None
-    } else {
-        Some(HCURSOR(lparam.0 as _))
-    };
-
-    if had_cursor != state.current_cursor.is_some() {
-        unsafe { SetCursor(state.current_cursor.as_ref()) };
-    }
-
+    state_ptr.state.borrow_mut().current_cursor = HCURSOR(lparam.0 as _);
     Some(0)
 }
 
@@ -1144,9 +1132,7 @@ fn handle_set_cursor(lparam: LPARAM, state_ptr: Rc<WindowsWindowStatePtr>) -> Op
     ) {
         return None;
     }
-    unsafe {
-        SetCursor(state_ptr.state.borrow().current_cursor.as_ref());
-    };
+    unsafe { SetCursor(state_ptr.state.borrow().current_cursor) };
     Some(1)
 }
 

crates/gpui/src/platform/windows/platform.rs 🔗

@@ -50,7 +50,7 @@ pub(crate) struct WindowsPlatformState {
     callbacks: PlatformCallbacks,
     menus: Vec<OwnedMenu>,
     // NOTE: standard cursor handles don't need to close.
-    pub(crate) current_cursor: Option<HCURSOR>,
+    pub(crate) current_cursor: HCURSOR,
 }
 
 #[derive(Default)]
@@ -506,11 +506,11 @@ impl Platform for WindowsPlatform {
     fn set_cursor_style(&self, style: CursorStyle) {
         let hcursor = load_cursor(style);
         let mut lock = self.state.borrow_mut();
-        if lock.current_cursor.map(|c| c.0) != hcursor.map(|c| c.0) {
+        if lock.current_cursor.0 != hcursor.0 {
             self.post_message(
                 WM_GPUI_CURSOR_STYLE_CHANGED,
                 WPARAM(0),
-                LPARAM(hcursor.map_or(0, |c| c.0 as isize)),
+                LPARAM(hcursor.0 as isize),
             );
             lock.current_cursor = hcursor;
         }
@@ -613,7 +613,7 @@ impl Drop for WindowsPlatform {
 pub(crate) struct WindowCreationInfo {
     pub(crate) icon: HICON,
     pub(crate) executor: ForegroundExecutor,
-    pub(crate) current_cursor: Option<HCURSOR>,
+    pub(crate) current_cursor: HCURSOR,
     pub(crate) windows_version: WindowsVersion,
     pub(crate) validation_number: usize,
     pub(crate) main_receiver: flume::Receiver<Runnable>,

crates/gpui/src/platform/windows/util.rs 🔗

@@ -105,7 +105,7 @@ pub(crate) fn windows_credentials_target_name(url: &str) -> String {
     format!("zed:url={}", url)
 }
 
-pub(crate) fn load_cursor(style: CursorStyle) -> Option<HCURSOR> {
+pub(crate) fn load_cursor(style: CursorStyle) -> HCURSOR {
     static ARROW: OnceLock<SafeCursor> = OnceLock::new();
     static IBEAM: OnceLock<SafeCursor> = OnceLock::new();
     static CROSS: OnceLock<SafeCursor> = OnceLock::new();
@@ -126,20 +126,17 @@ pub(crate) fn load_cursor(style: CursorStyle) -> Option<HCURSOR> {
         | CursorStyle::ResizeUpDown
         | CursorStyle::ResizeRow => (&SIZENS, IDC_SIZENS),
         CursorStyle::OperationNotAllowed => (&NO, IDC_NO),
-        CursorStyle::None => return None,
         _ => (&ARROW, IDC_ARROW),
     };
-    Some(
-        *(*lock.get_or_init(|| {
-            HCURSOR(
-                unsafe { LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED) }
-                    .log_err()
-                    .unwrap_or_default()
-                    .0,
-            )
-            .into()
-        })),
-    )
+    *(*lock.get_or_init(|| {
+        HCURSOR(
+            unsafe { LoadImageW(None, name, IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED) }
+                .log_err()
+                .unwrap_or_default()
+                .0,
+        )
+        .into()
+    }))
 }
 
 /// This function is used to configure the dark mode for the window built-in title bar.

crates/gpui/src/platform/windows/window.rs 🔗

@@ -49,7 +49,7 @@ pub struct WindowsWindowState {
 
     pub click_state: ClickState,
     pub system_settings: WindowsSystemSettings,
-    pub current_cursor: Option<HCURSOR>,
+    pub current_cursor: HCURSOR,
     pub nc_button_pressed: Option<u32>,
 
     pub display: WindowsDisplay,
@@ -77,7 +77,7 @@ impl WindowsWindowState {
         hwnd: HWND,
         transparent: bool,
         cs: &CREATESTRUCTW,
-        current_cursor: Option<HCURSOR>,
+        current_cursor: HCURSOR,
         display: WindowsDisplay,
         gpu_context: &BladeContext,
     ) -> Result<Self> {
@@ -352,7 +352,7 @@ struct WindowCreateContext<'a> {
     transparent: bool,
     is_movable: bool,
     executor: ForegroundExecutor,
-    current_cursor: Option<HCURSOR>,
+    current_cursor: HCURSOR,
     windows_version: WindowsVersion,
     validation_number: usize,
     main_receiver: flume::Receiver<Runnable>,

crates/gpui/src/window.rs 🔗

@@ -3233,7 +3233,6 @@ impl Window {
             keystroke,
             &dispatch_path,
         );
-
         if !match_result.to_replay.is_empty() {
             self.replay_pending_input(match_result.to_replay, cx)
         }

crates/gpui_macros/src/styles.rs 🔗

@@ -326,13 +326,6 @@ pub fn cursor_style_methods(input: TokenStream) -> TokenStream {
             self.style().mouse_cursor = Some(gpui::CursorStyle::ResizeLeft);
             self
         }
-
-        /// Sets cursor style when hovering over an element to `none`.
-        /// [Docs](https://tailwindcss.com/docs/cursor)
-        #visibility fn cursor_none(mut self, cursor: CursorStyle) -> Self {
-            self.style().mouse_cursor = Some(gpui::CursorStyle::None);
-            self
-        }
     };
 
     output.into()

docs/src/configuring-zed.md 🔗

@@ -533,16 +533,6 @@ List of `string` values
 "cursor_shape": "hollow"
 ```
 
-## Hide Mouse While Typing
-
-- Description: Determines whether the mouse cursor should be hidden while typing in an editor or input box.
-- Setting: `hide_mouse_while_typing`
-- Default: `true`
-
-**Options**
-
-`boolean` values
-
 ## Editor Scrollbar
 
 - Description: Whether or not to show the editor scrollbar and various elements in it.