G1: limit Cmd+Alt Group Selection to active Direct Selection

Pen Cmd-borrow keeps Direct Selection when Alt is held so guide copy and other Alt modifiers on the lent tool still work.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
nrq6993-a11y
2026-10-21 23:38:02 +07:00
committed by bflatastic
co-authored by Cursor
parent fface52206
commit 2dcceea8e1
3 changed files with 8 additions and 10 deletions
+3 -2
View File
@@ -1609,14 +1609,15 @@ fn pen_with_cmd_borrows_direct_selection_and_goes_on_drawing() {
}
#[test]
fn cmd_alt_lends_group_selection_when_direct_selection_was_last() {
fn cmd_alt_lends_group_selection_while_direct_selection_is_active() {
let (cmd, cmd_alt) = (Mods { cmd: true, ..Mods::default() }, Mods { cmd: true, alt: true, ..Mods::default() });
let v = view();
let mut s = session();
// Cmd+Alt while the Pen borrows Direct Selection keeps Direct Selection (Alt is copy/subtract).
s.select_tool("directSelection", v).unwrap();
s.select_tool("pen", v).unwrap();
s.pointer(&PointerEvent::new(PointerKind::Down, 50.0, 50.0).with_mods(cmd_alt), v).unwrap();
assert_eq!(s.tool_id(), "groupSelection");
assert_eq!(s.tool_id(), "directSelection");
s.pointer(&PointerEvent::new(PointerKind::Up, 50.0, 50.0).with_mods(cmd_alt), v).unwrap();
assert_eq!(s.tool_id(), "pen");
// Cmd alone still lends Direct Selection.
+4 -7
View File
@@ -104,8 +104,9 @@ impl Session {
/// The selection tool Cmd lends tool `id` for a drag: the one chosen last; until one is,
/// Direct Selection to the tools that edit anchors (the Pen) and Selection to the others.
/// Cmd+Alt lends Group Selection when the lend would be Direct Selection (including while
/// Direct Selection is active). None for the other selection tools and the view tools.
/// Cmd+Alt lends Group Selection while Direct Selection is active. Cmd still lends the last
/// selection tool from other tools (Alt on the lent Direct Selection gesture stays copy/subtract).
/// None for the other selection tools and the view tools.
fn lent_tool(&self, id: &str, mods: &Mods) -> Option<&'static str> {
use vectorcraft_tools::catalog::{edits_anchors, is_selection_tool};
if matches!(id, "hand" | "zoom" | "rotateView") {
@@ -117,11 +118,7 @@ impl Session {
if is_selection_tool(id) {
return None;
}
let base = self.last_selection_tool.unwrap_or(if edits_anchors(id) { "directSelection" } else { "selection" });
if mods.alt && base == "directSelection" {
return Some("groupSelection");
}
Some(base)
Some(self.last_selection_tool.unwrap_or(if edits_anchors(id) { "directSelection" } else { "selection" }))
}
/// A press with Cmd held (Ctrl elsewhere) and any other tool than a selection tool: the
+1 -1
View File
@@ -168,7 +168,7 @@ tools, never checked side by side) isn't captured row by row.
|---|---|---|
| Space: Hand; Cmd+Space / Cmd+Alt+Space: zoom in/out; middle button pans | done | |
| Document window scroll bars along the right and bottom edges (Normal and Full Screen Mode with Menu Bar; none in Full Screen and Presentation Mode): a thumb as long as the view against the art and the artboards; dragging it scrolls, a click on the track pages, the wheel over a bar scrolls along it; in a rotated view they follow the screen's axes | partial | #2322. The span is the art and the artboards with half a window around them, not Illustrator's 227 in canvas: VectorCraft has no bounded drawing area (#2284). A track click pages rather than jumping to the click; the page size and the rotated-view behaviour are our own choice (the public documentation gives neither) |
| Cmd/Ctrl: last-used selection tool; Cmd+Alt: Group Selection inside Direct Selection | done | Cmd+Alt lends Group Selection when the lend would be Direct Selection, including while Direct Selection is active; engine pointer regressions |
| Cmd/Ctrl: last-used selection tool; Cmd+Alt: Group Selection inside Direct Selection | done | Cmd+Alt lends Group Selection only while Direct Selection is active (Cmd borrow from the Pen keeps Direct Selection so Alt stays copy/subtract); engine pointer regressions |
| Eyedropper reads visible sources while their layer/object is locked or outside isolation | done | Ordinary/Shift/Shift+Alt and gradient-stop reads preserve the source and selection; Alt reverse remains editable-only; hidden art stays excluded (`eyedropper_sources.rs`, #1251) |
| Add a visible stroke after drawing with inherited None/zero-width paint | done | Paint and Swap Fill/Stroke restore the existing 1 pt default; positive widths and painted zero widths stay as set; Undo/Redo and targeted appearance items tested (`stroke_visibility.rs`, #1253) |
| Double-click a stroked segment to create a width point in Width Point Edit | done | Finite-arithmetic follow-up: engine regressions and full CI passed; [Validation evidence](target-app-parity.md#evidence-what-ships-today-by-area). Command and pointer regressions cover opening, sampled widths, adjoining adjustment on/off through checkbox/OK, compound paths, Cancel/Delete and Undo/Redo; dialog layout reviewed. [Validation evidence](target-app-parity.md#evidence-what-ships-today-by-area) |