@@ -910,7 +910,10 @@ enum SelectionDragState {
/// State when no drag related activity is detected.
None,
/// State when the mouse is down on a selection that is about to be dragged.
- ReadyToDrag { selection: Selection<Anchor> },
+ ReadyToDrag {
+ selection: Selection<Anchor>,
+ click_position: gpui::Point<Pixels>,
+ },
/// State when the mouse is dragging the selection in the editor.
Dragging {
selection: Selection<Anchor>,
@@ -10601,54 +10604,42 @@ impl Editor {
});
}
- pub fn drop_selection(
+ pub fn move_selection_on_drop(
&mut self,
- point_for_position: Option<PointForPosition>,
+ selection: &Selection<Anchor>,
+ target: DisplayPoint,
is_cut: bool,
window: &mut Window,
cx: &mut Context<Self>,
- ) -> bool {
- if let Some(point_for_position) = point_for_position {
- match self.selection_drag_state {
- SelectionDragState::Dragging { ref selection, .. } => {
- let snapshot = self.snapshot(window, cx);
- let selection_display =
- selection.map(|anchor| anchor.to_display_point(&snapshot));
- if !point_for_position.intersects_selection(&selection_display) {
- let point = point_for_position.previous_valid;
- let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
- let buffer = &display_map.buffer_snapshot;
- let mut edits = Vec::new();
- let insert_point = display_map
- .clip_point(point, Bias::Left)
- .to_point(&display_map);
- let text = buffer
- .text_for_range(selection.start..selection.end)
- .collect::<String>();
- if is_cut {
- edits.push(((selection.start..selection.end), String::new()));
- }
- let insert_anchor = buffer.anchor_before(insert_point);
- edits.push(((insert_anchor..insert_anchor), text));
- let last_edit_start = insert_anchor.bias_left(buffer);
- let last_edit_end = insert_anchor.bias_right(buffer);
- self.transact(window, cx, |this, window, cx| {
- this.buffer.update(cx, |buffer, cx| {
- buffer.edit(edits, None, cx);
- });
- this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
- s.select_anchor_ranges([last_edit_start..last_edit_end]);
- });
- });
- self.selection_drag_state = SelectionDragState::None;
- return true;
- }
- }
- _ => {}
- }
+ ) {
+ let display_map = self.display_map.update(cx, |map, cx| map.snapshot(cx));
+ let buffer = &display_map.buffer_snapshot;
+ let mut edits = Vec::new();
+ let insert_point = display_map
+ .clip_point(target, Bias::Left)
+ .to_point(&display_map);
+ let text = buffer
+ .text_for_range(selection.start..selection.end)
+ .collect::<String>();
+ if is_cut {
+ edits.push(((selection.start..selection.end), String::new()));
}
+ let insert_anchor = buffer.anchor_before(insert_point);
+ edits.push(((insert_anchor..insert_anchor), text));
+ let last_edit_start = insert_anchor.bias_left(buffer);
+ let last_edit_end = insert_anchor.bias_right(buffer);
+ self.transact(window, cx, |this, window, cx| {
+ this.buffer.update(cx, |buffer, cx| {
+ buffer.edit(edits, None, cx);
+ });
+ this.change_selections(Some(Autoscroll::fit()), window, cx, |s| {
+ s.select_anchor_ranges([last_edit_start..last_edit_end]);
+ });
+ });
+ }
+
+ pub fn clear_selection_drag_state(&mut self) {
self.selection_drag_state = SelectionDragState::None;
- false
}
pub fn duplicate(
@@ -641,6 +641,7 @@ impl EditorElement {
if point_for_position.intersects_selection(&selection) {
editor.selection_drag_state = SelectionDragState::ReadyToDrag {
selection: newest_anchor.clone(),
+ click_position: event.position,
};
cx.stop_propagation();
return;
@@ -832,9 +833,44 @@ impl EditorElement {
let pending_nonempty_selections = editor.has_pending_nonempty_selection();
let point_for_position = position_map.point_for_position(event.position);
- let is_cut = !event.modifiers.control;
- if editor.drop_selection(Some(point_for_position), is_cut, window, cx) {
- return;
+ match editor.selection_drag_state {
+ SelectionDragState::ReadyToDrag {
+ selection: _,
+ ref click_position,
+ } => {
+ if event.position == *click_position {
+ editor.select(
+ SelectPhase::Begin {
+ position: point_for_position.previous_valid,
+ add: false,
+ click_count: 1, // ready to drag state only occurs on click count 1
+ },
+ window,
+ cx,
+ );
+ editor.selection_drag_state = SelectionDragState::None;
+ cx.stop_propagation();
+ return;
+ }
+ }
+ 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;
+ editor.move_selection_on_drop(
+ &selection.clone(),
+ point_for_position.previous_valid,
+ is_cut,
+ window,
+ cx,
+ );
+ editor.selection_drag_state = SelectionDragState::None;
+ cx.stop_propagation();
+ return;
+ }
+ }
+ _ => {}
}
if end_selection {
@@ -951,7 +987,7 @@ impl EditorElement {
drop_cursor.start = drop_anchor;
drop_cursor.end = drop_anchor;
}
- SelectionDragState::ReadyToDrag { ref selection } => {
+ SelectionDragState::ReadyToDrag { ref selection, .. } => {
let drop_cursor = Selection {
id: post_inc(&mut editor.selections.next_selection_id),
start: drop_anchor,
@@ -915,8 +915,8 @@ impl Vim {
if mode == Mode::Normal || mode != last_mode {
self.current_tx.take();
self.current_anchor.take();
- self.update_editor(window, cx, |_, editor, window, cx| {
- editor.drop_selection(None, false, window, cx);
+ self.update_editor(window, cx, |_, editor, _, _| {
+ editor.clear_selection_drag_state();
});
}
Vim::take_forced_motion(cx);