diff --git a/core/shortcut_items.ts b/core/shortcut_items.ts index 77f29b98d..6a7e29d26 100644 --- a/core/shortcut_items.ts +++ b/core/shortcut_items.ts @@ -17,6 +17,8 @@ import {KeyCodes} from './utils/keycodes.js'; import type {WorkspaceSvg} from './workspace_svg.js'; import {isDraggable} from './interfaces/i_draggable.js'; import * as eventUtils from './events/utils.js'; +import {Coordinate} from './utils/coordinate.js'; +import {Rect} from './utils/rect.js'; /** * Object holding the names of the default shortcut items. @@ -90,6 +92,7 @@ export function registerDelete() { let copyData: ICopyData | null = null; let copyWorkspace: WorkspaceSvg | null = null; +let copyCoords: Coordinate | null = null; /** * Keyboard shortcut to copy a block on ctrl+c, cmd+c, or alt+c. @@ -129,6 +132,9 @@ export function registerCopy() { if (!selected || !isCopyable(selected)) return false; copyData = selected.toCopyData(); copyWorkspace = workspace; + copyCoords = isDraggable(selected) + ? selected.getRelativeToSurfaceXY() + : null; return !!copyData; }, keyCodes: [ctrlC, altC, metaC], @@ -171,6 +177,7 @@ export function registerCut() { if (selected instanceof BlockSvg) { copyData = selected.toCopyData(); copyWorkspace = workspace; + copyCoords = selected.getRelativeToSurfaceXY(); selected.checkAndDelete(); return true; } else if ( @@ -180,6 +187,9 @@ export function registerCut() { ) { copyData = selected.toCopyData(); copyWorkspace = workspace; + copyCoords = isDraggable(selected) + ? selected.getRelativeToSurfaceXY() + : null; selected.dispose(); return true; } @@ -212,7 +222,26 @@ export function registerPaste() { }, callback() { if (!copyData || !copyWorkspace) return false; - return !!clipboard.paste(copyData, copyWorkspace); + if (!copyCoords) { + // If we don't have location data about the original copyable, let the + // paster determine position. + return !!clipboard.paste(copyData, copyWorkspace); + } + + const {left, top, width, height} = copyWorkspace + .getMetricsManager() + .getViewMetrics(true); + const viewportRect = new Rect(top, top + height, left, left + width); + + if (viewportRect.contains(copyCoords.x, copyCoords.y)) { + // If the original copyable is inside the viewport, let the paster + // determine position. + return !!clipboard.paste(copyData, copyWorkspace); + } + + // Otherwise, paste in the middle of the viewport. + const centerCoords = new Coordinate(left + width / 2, top + height / 2); + return !!clipboard.paste(copyData, copyWorkspace, centerCoords); }, keyCodes: [ctrlV, altV, metaV], };