Fix mouse multi cursor placement for wrapped lines (#61590) (cherry-pick to preview) (#61778)
Some checks are pending
run_tests / check_style (push) Waiting to run
run_tests / clippy_mac (push) Blocked by required conditions
run_tests / clippy_mac_x86_64 (push) Blocked by required conditions
run_tests / orchestrate (push) Waiting to run
run_tests / clippy_windows (push) Blocked by required conditions
run_tests / clippy_linux (push) Blocked by required conditions
run_tests / check_docs (push) Blocked by required conditions
run_tests / check_licenses (push) Blocked by required conditions
run_tests / check_scripts (push) Blocked by required conditions
run_tests / check_postgres_and_protobuf_migrations (push) Blocked by required conditions
run_tests / extension_tests (push) Blocked by required conditions
run_tests / tests_pass (push) Blocked by required conditions
run_tests / run_tests_windows (push) Blocked by required conditions
run_tests / run_tests_linux (push) Blocked by required conditions
run_tests / run_tests_mac (push) Blocked by required conditions
run_tests / miri_scheduler (push) Blocked by required conditions
run_tests / doctests (push) Blocked by required conditions
run_tests / check_workspace_binaries (push) Blocked by required conditions
run_tests / build_visual_tests_binary (push) Blocked by required conditions
run_tests / check_wasm (push) Blocked by required conditions
run_tests / check_dependencies (push) Blocked by required conditions

Cherry-pick of #61590 to preview

----
Closes https://github.com/zed-industries/zed/issues/25237



https://github.com/user-attachments/assets/0f1d54a0-c8f1-4b49-8327-73375a2e1f4e


Release Notes:

- Fixed mouse multi cursor placement for wrapped lines

---------

Co-authored-by: Finn Evers <finn@zed.dev>

Co-authored-by: Kirill Bulatov <kirill@zed.dev>
Co-authored-by: Finn Evers <finn@zed.dev>
This commit is contained in:
zed-zippy[bot] 2026-07-28 13:09:57 +00:00 committed by GitHub
parent 16cb1e3cdb
commit b975bd10fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 88 additions and 0 deletions

View file

@ -41812,6 +41812,87 @@ async fn test_columnar_selection_past_end_of_line(cx: &mut TestAppContext) {
"});
}
#[gpui::test]
async fn test_columnar_selection_with_soft_wrap(cx: &mut TestAppContext) {
init_test(cx, |_| {});
let mut cx = EditorTestContext::new(cx).await;
cx.set_state(indoc! {"
ˇ1. Very long line to show how a wrapped line would look
2. Very long line to show how a wrapped line would look
"});
let soft_wrap_second_line_row = |editor: &mut Editor, cx: &mut Context<Editor>| {
editor.set_wrap_width(Some(100.0.into()), cx);
let snapshot = editor.display_snapshot(cx);
let second_line_row = Point::new(1, 0).to_display_point(&snapshot).row();
assert!(
second_line_row.0 > 1,
"expected the first line to be soft wrapped"
);
second_line_row
};
// Dragging a columnar selection across the soft-wrapped rows of the first
// line must produce one selection per buffer line, not one per display row.
cx.update_editor(|editor, window, cx| {
let second_line_row = soft_wrap_second_line_row(editor, cx);
editor.select(
SelectPhase::BeginColumnar {
position: DisplayPoint::new(DisplayRow(0), 0),
goal_column: 0,
reset: true,
mode: ColumnarMode::FromMouse,
},
window,
cx,
);
editor.select(
SelectPhase::Update {
position: DisplayPoint::new(second_line_row, 1),
goal_column: 1,
scroll_delta: gpui::Point::default(),
},
window,
cx,
);
});
cx.assert_editor_state(indoc! {"
«1ˇ». Very long line to show how a wrapped line would look
«2ˇ». Very long line to show how a wrapped line would look
"});
cx.update_editor(|editor, window, cx| {
let second_line_row = soft_wrap_second_line_row(editor, cx);
editor.select(
SelectPhase::BeginColumnar {
position: DisplayPoint::new(DisplayRow(0), 0),
goal_column: 0,
reset: true,
mode: ColumnarMode::FromMouse,
},
window,
cx,
);
editor.select(
SelectPhase::Update {
position: DisplayPoint::new(second_line_row, 0),
goal_column: 0,
scroll_delta: gpui::Point::default(),
},
window,
cx,
);
});
cx.assert_editor_state(indoc! {"
ˇ1. Very long line to show how a wrapped line would look
ˇ2. Very long line to show how a wrapped line would look
"});
}
#[gpui::test]
async fn test_toggle_markdown_block_quote(cx: &mut TestAppContext) {
init_test(cx, |_| {});

View file

@ -1809,6 +1809,7 @@ impl Editor {
let end_x = tail_x.max(head_x);
let reversed = head_x < tail_x;
let mut last_buffer_row = None;
let selection_ranges = (start_row.0..=end_row.0)
.map(DisplayRow)
.filter_map(|row| {
@ -1816,6 +1817,12 @@ impl Editor {
return None;
}
let buffer_row = row.as_display_point().to_point(display_map).row;
if last_buffer_row == Some(buffer_row) {
return None;
}
last_buffer_row = Some(buffer_row);
let layout = display_map.layout_row(row, &text_layout_details);
if matches!(columnar_state, ColumnarSelectionState::FromSelection { .. })
&& start_x > layout.width