mirror of
https://github.com/storytold/figcraft.git
synced 2026-10-28 20:36:55 -06:00
fix(ui): a V held while the window was away doesn't paste on release (#663)
winit sends no press for a key held across a focus change (X11's synthetic presses are dropped by egui-winit), so letting go of V after coming back looked like a swallowed Cmd+V. After a focus gain, a V release only pastes with Cmd still held. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
40955aae7c
commit
4adbd6cee9
@@ -500,6 +500,8 @@ pub struct UiState {
|
||||
/// (`shortcuts::swallowed_paste`).
|
||||
pub v_pressed: bool,
|
||||
pub paste_event: bool,
|
||||
/// The window got the focus back since the last V release.
|
||||
pub refocused: bool,
|
||||
/// When (UI clock, seconds) open documents next get an autosave checkpoint.
|
||||
pub next_autosave: f64,
|
||||
/// With auto-save on: when (UI clock, seconds) files with unsaved changes are next saved, and
|
||||
@@ -595,6 +597,7 @@ impl Default for UiState {
|
||||
last_copy: None,
|
||||
v_pressed: false,
|
||||
paste_event: false,
|
||||
refocused: false,
|
||||
next_autosave: 0.0,
|
||||
auto_save_at: None,
|
||||
auto_saving: Vec::new(),
|
||||
|
||||
@@ -200,6 +200,30 @@ fn a_v_press_lost_to_another_window_does_not_block_the_next_cmd_v() {
|
||||
assert_eq!(w.named("Pasted image"), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn v_held_while_the_window_was_away_pastes_nothing_on_release() {
|
||||
let mut w = Win::new();
|
||||
w.copy_image_elsewhere();
|
||||
// Pressed in another window: only the focus and the release arrive here.
|
||||
w.frame(vec![Event::WindowFocused(true)]);
|
||||
w.frame(vec![key(Key::V, false, Modifiers::NONE)]);
|
||||
w.frame(vec![]);
|
||||
assert_eq!(w.named("Pasted image"), 0);
|
||||
w.cmd_v(CMD);
|
||||
assert_eq!(w.named("Pasted image"), 1, "the next Cmd+V still pastes");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cmd_v_in_a_panel_field_does_not_paste_on_the_canvas() {
|
||||
let mut w = Win::new();
|
||||
w.copy_image_elsewhere();
|
||||
w.frame(vec![]);
|
||||
w.app.field_focus = true;
|
||||
w.frame(vec![key(Key::V, false, CMD)]);
|
||||
w.frame(vec![]);
|
||||
assert_eq!(w.named("Pasted image"), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn paste_here_prefers_a_newer_image_over_copied_layers() {
|
||||
let mut w = Win::new();
|
||||
|
||||
@@ -146,10 +146,13 @@ pub fn swallowed_paste(app: &mut FigApp, ctx: &Context) -> bool {
|
||||
Event::Paste(_) => ui.paste_event = true,
|
||||
Event::Key { key: Key::V, pressed: true, .. } => ui.v_pressed = true,
|
||||
Event::Key { key: Key::V, pressed: false, modifiers, .. } => {
|
||||
// Shift or Alt with it is another command (paste over, paste properties).
|
||||
paste = !ui.v_pressed && !ui.paste_event && !modifiers.shift && !modifiers.alt;
|
||||
// Shift or Alt with it is another command (paste over, paste properties). A V
|
||||
// held while the window was away comes back as a release alone: without Cmd
|
||||
// held, that's no paste.
|
||||
paste = !ui.v_pressed && !ui.paste_event && !modifiers.shift && !modifiers.alt && (modifiers.command || !ui.refocused);
|
||||
ui.v_pressed = false;
|
||||
ui.paste_event = false;
|
||||
ui.refocused = false;
|
||||
}
|
||||
// The other keys that paste (Shift+Insert, a Paste key) end their paste event.
|
||||
Event::Key { key: Key::Insert | Key::Paste, pressed: false, .. } => ui.paste_event = false,
|
||||
@@ -158,6 +161,7 @@ pub fn swallowed_paste(app: &mut FigApp, ctx: &Context) -> bool {
|
||||
ui.v_pressed = false;
|
||||
ui.paste_event = false;
|
||||
}
|
||||
Event::WindowFocused(true) => ui.refocused = true,
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user