From eb5f59577d637f2ce2dc6da1920b724fa44cf536 Mon Sep 17 00:00:00 2001 From: CharlesChen0823 Date: Tue, 10 Jun 2025 18:11:59 +0800 Subject: [PATCH] editor: Dismiss drag selection when dropped outside editor (#32382) This PR fixes two issues: 1. On macOS, using Alt to copy the selection instead of cutting it. 2. Dropping the drag selection outside the editor dismisses it. https://github.com/user-attachments/assets/341e21c3-3eca-4e58-9bcc-8ec1de18e999 Release Notes: - N/A --------- Co-authored-by: Smit Barmase --- crates/editor/src/editor.rs | 1 + crates/editor/src/element.rs | 38 +++++++++++++++++++++++------------- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index b0710240d7..5ff649222e 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -918,6 +918,7 @@ enum SelectionDragState { Dragging { selection: Selection, drop_cursor: Selection, + hide_drop_cursor: bool, }, } diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 52101f35fd..7c2f2c8845 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -856,8 +856,11 @@ impl EditorElement { SelectionDragState::Dragging { ref selection, .. } => { let snapshot = editor.snapshot(window, cx); let selection_display = selection.map(|anchor| anchor.to_display_point(&snapshot)); - if !point_for_position.intersects_selection(&selection_display) { - let is_cut = !event.modifiers.control; + if !point_for_position.intersects_selection(&selection_display) + && text_hitbox.is_hovered(window) + { + let is_cut = !(cfg!(target_os = "macos") && event.modifiers.alt + || cfg!(not(target_os = "macos")) && event.modifiers.control); editor.move_selection_on_drop( &selection.clone(), point_for_position.previous_valid, @@ -865,10 +868,11 @@ impl EditorElement { window, cx, ); - editor.selection_drag_state = SelectionDragState::None; - cx.stop_propagation(); - return; } + editor.selection_drag_state = SelectionDragState::None; + cx.stop_propagation(); + cx.notify(); + return; } _ => {} } @@ -941,7 +945,8 @@ impl EditorElement { return; } - let text_bounds = position_map.text_hitbox.bounds; + let text_hitbox = &position_map.text_hitbox; + let text_bounds = text_hitbox.bounds; let point_for_position = position_map.point_for_position(event.position); let mut scroll_delta = gpui::Point::::default(); @@ -982,10 +987,12 @@ impl EditorElement { match editor.selection_drag_state { SelectionDragState::Dragging { ref mut drop_cursor, + ref mut hide_drop_cursor, .. } => { drop_cursor.start = drop_anchor; drop_cursor.end = drop_anchor; + *hide_drop_cursor = !text_hitbox.is_hovered(window); } SelectionDragState::ReadyToDrag { ref selection, .. } => { let drop_cursor = Selection { @@ -998,6 +1005,7 @@ impl EditorElement { editor.selection_drag_state = SelectionDragState::Dragging { selection: selection.clone(), drop_cursor, + hide_drop_cursor: false, }; } _ => {} @@ -1251,16 +1259,18 @@ impl EditorElement { if let SelectionDragState::Dragging { ref selection, ref drop_cursor, + ref hide_drop_cursor, } = editor.selection_drag_state { - if drop_cursor - .start - .cmp(&selection.start, &snapshot.buffer_snapshot) - .eq(&Ordering::Less) - || drop_cursor - .end - .cmp(&selection.end, &snapshot.buffer_snapshot) - .eq(&Ordering::Greater) + if !hide_drop_cursor + && (drop_cursor + .start + .cmp(&selection.start, &snapshot.buffer_snapshot) + .eq(&Ordering::Less) + || drop_cursor + .end + .cmp(&selection.end, &snapshot.buffer_snapshot) + .eq(&Ordering::Greater)) { let drag_cursor_layout = SelectionLayout::new( drop_cursor.clone(),