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 <heysmitbarmase@gmail.com>
This commit is contained in:
CharlesChen0823 2025-06-10 18:11:59 +08:00 committed by GitHub
parent 2dad48d8d9
commit eb5f59577d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 25 additions and 14 deletions

View file

@ -918,6 +918,7 @@ enum SelectionDragState {
Dragging { Dragging {
selection: Selection<Anchor>, selection: Selection<Anchor>,
drop_cursor: Selection<Anchor>, drop_cursor: Selection<Anchor>,
hide_drop_cursor: bool,
}, },
} }

View file

@ -856,8 +856,11 @@ impl EditorElement {
SelectionDragState::Dragging { ref selection, .. } => { SelectionDragState::Dragging { ref selection, .. } => {
let snapshot = editor.snapshot(window, cx); let snapshot = editor.snapshot(window, cx);
let selection_display = selection.map(|anchor| anchor.to_display_point(&snapshot)); let selection_display = selection.map(|anchor| anchor.to_display_point(&snapshot));
if !point_for_position.intersects_selection(&selection_display) { if !point_for_position.intersects_selection(&selection_display)
let is_cut = !event.modifiers.control; && 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( editor.move_selection_on_drop(
&selection.clone(), &selection.clone(),
point_for_position.previous_valid, point_for_position.previous_valid,
@ -865,10 +868,11 @@ impl EditorElement {
window, window,
cx, 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; 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 point_for_position = position_map.point_for_position(event.position);
let mut scroll_delta = gpui::Point::<f32>::default(); let mut scroll_delta = gpui::Point::<f32>::default();
@ -982,10 +987,12 @@ impl EditorElement {
match editor.selection_drag_state { match editor.selection_drag_state {
SelectionDragState::Dragging { SelectionDragState::Dragging {
ref mut drop_cursor, ref mut drop_cursor,
ref mut hide_drop_cursor,
.. ..
} => { } => {
drop_cursor.start = drop_anchor; drop_cursor.start = drop_anchor;
drop_cursor.end = drop_anchor; drop_cursor.end = drop_anchor;
*hide_drop_cursor = !text_hitbox.is_hovered(window);
} }
SelectionDragState::ReadyToDrag { ref selection, .. } => { SelectionDragState::ReadyToDrag { ref selection, .. } => {
let drop_cursor = Selection { let drop_cursor = Selection {
@ -998,6 +1005,7 @@ impl EditorElement {
editor.selection_drag_state = SelectionDragState::Dragging { editor.selection_drag_state = SelectionDragState::Dragging {
selection: selection.clone(), selection: selection.clone(),
drop_cursor, drop_cursor,
hide_drop_cursor: false,
}; };
} }
_ => {} _ => {}
@ -1251,16 +1259,18 @@ impl EditorElement {
if let SelectionDragState::Dragging { if let SelectionDragState::Dragging {
ref selection, ref selection,
ref drop_cursor, ref drop_cursor,
ref hide_drop_cursor,
} = editor.selection_drag_state } = editor.selection_drag_state
{ {
if drop_cursor if !hide_drop_cursor
.start && (drop_cursor
.cmp(&selection.start, &snapshot.buffer_snapshot) .start
.eq(&Ordering::Less) .cmp(&selection.start, &snapshot.buffer_snapshot)
|| drop_cursor .eq(&Ordering::Less)
.end || drop_cursor
.cmp(&selection.end, &snapshot.buffer_snapshot) .end
.eq(&Ordering::Greater) .cmp(&selection.end, &snapshot.buffer_snapshot)
.eq(&Ordering::Greater))
{ {
let drag_cursor_layout = SelectionLayout::new( let drag_cursor_layout = SelectionLayout::new(
drop_cursor.clone(), drop_cursor.clone(),