From 685448a0b28c49dd78ab05d0aa0db4d8bf9d55a3 Mon Sep 17 00:00:00 2001 From: Jerome CAMUS Date: Fri, 23 Oct 2026 16:06:08 +0200 Subject: [PATCH] Fix #2091 copy a named layer even when a mask is selected edit.copy {"layer": id} copied the selected mask instead of the layer: the mask branch only checked for `layers`, but `layer` is an explicit target too. Co-Authored-By: Claude Sonnet 5.5 --- crates/engine/src/cmd/edit.rs | 5 +++-- crates/engine/src/tests/menu_cmds.rs | 13 +++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/cmd/edit.rs b/crates/engine/src/cmd/edit.rs index 594f01d29..8a5068e8f 100644 --- a/crates/engine/src/cmd/edit.rs +++ b/crates/engine/src/cmd/edit.rs @@ -313,8 +313,9 @@ fn copy(s: &mut Session, p: &Value) -> Result { if p.get("layers").is_none() && !super::effect::selected_effects(s).is_empty() { return s.execute("effect.copy", json!({})); } - // Masks selected → copy them (not their layer), for Paste onto other layers (#2091). - if p.get("layers").is_none() { + // Masks selected → copy them (not their layer), for Paste onto other layers (#2091), unless + // a layer is named explicitly. + if p.get("layers").is_none() && p.get("layer").is_none_or(Value::is_null) { let masks = super::prop_groups::copy_masks(s); if !masks.is_empty() { clear_clipboards(s); diff --git a/crates/engine/src/tests/menu_cmds.rs b/crates/engine/src/tests/menu_cmds.rs index 95ed5d8d8..bf4daf1a4 100644 --- a/crates/engine/src/tests/menu_cmds.rs +++ b/crates/engine/src/tests/menu_cmds.rs @@ -1993,3 +1993,16 @@ fn paste_masks_skips_locked_layers() { assert!(s.execute("edit.paste", json!({})).is_err()); assert_eq!(layer(&s, b).masks().unwrap().groups().count(), 0); } + +#[test] +fn copy_with_an_explicit_layer_ignores_the_selected_mask() { + let mut s = comp(); + let a = solid(&mut s, "#ff0000"); + s.execute("layer.select", json!({"layers": [a]})).unwrap(); + s.execute("layer.addMask", json!({})).unwrap(); + let mask = layer(&s, a).masks().unwrap().groups().next().unwrap().uid; + s.execute("prop.select", json!({"layer": a, "prop": mask})).unwrap(); + s.execute("edit.copy", json!({"layer": a})).unwrap(); + assert_eq!(s.state.clipboard.len(), 1, "the named layer is copied"); + assert!(s.state.mask_clipboard.is_empty()); +}