Technical details:
- skip LayerForge canvas and panel shortcuts when focus is inside editable controls
- patch ComfyUI ChangeTracker undoRedo so Ctrl/Cmd+Z does not leak to graph history while LayerForge owns the shortcut context
- stop clipboard copy/cut/paste events from editable LayerForge UI from bubbling into ComfyUI node clipboard handlers
- route widget-root Ctrl/Cmd+Z, Ctrl/Cmd+Y, and Ctrl/Cmd+Shift+Z through LayerForge canvas undo and redo when the widget is active
Implements two new features:
- Layer copy/paste within canvas using Ctrl+C/V
- Node duplication that preserves all layers
Layer Copy/Paste:
- Added Ctrl+V keyboard shortcut handler for pasting layers
- Intercept keydown events during capture phase to handle before ComfyUI
- Focus canvas when layer is clicked to ensure shortcuts work
- Prevent layers panel from stealing focus on mousedown
Node Duplication:
- Store source node ID during serialize for copy operations
- Track pending copy sources across node ID changes (-1 to real ID)
- Copy canvas state from source to destination in onAdded hook
- Use Map to persist copy metadata through node lifecycle
Ensure the canvas element is actually connected to the DOM before
handling paste events. This prevents LayerForge from capturing paste
events when navigating in subgraphs where the canvas is not visible.
Adds check for canvas.isConnected and document.body.contains() to
verify the canvas is part of the active DOM tree.
Prevent LayerForge from intercepting Ctrl+C, Ctrl+V, and other keyboard
shortcuts when the canvas is not focused. This was causing unwanted
popups and interfering with other nodes in ComfyUI.
Changes:
- Remove document.body focus check from handlePasteEvent
- Add focus validation to handleKeyDown before processing shortcuts
- Modifier keys (Ctrl, Shift, Alt, Meta) are still tracked globally
- All other shortcuts only trigger when canvas is focused
Fixes issue where paste events were captured globally regardless of focus.
Implemented grab icon feature in transform mode to move selected layers without changing selection, even when behind other layers. Added hover detection, cursor updates, and visual rendering in CanvasInteractions.ts and CanvasRenderer.ts.
Implemented drag-to-resize functionality for the output area with visual transform handles on corners and edges. Users can now interactively resize the output area by dragging handles instead of using dialogs, with support for grid snapping and aspect ratio preservation.
Implemented dynamic brush cursor with visual feedback for size (circle radius), strength (opacity), and hardness (solid/dashed border with gradient). Added overlay canvas system for smooth cursor updates without affecting main rendering performance.
Implemented centralized modifier state management with ModifierState interface and getModifierState() method. This eliminates inconsistencies between event-based and state-based modifier checking across mouse, wheel, and keyboard interactions.
Fixed all TypeScript compilation errors by defining a dedicated TransformOrigin type and adding proper null checks. Implemented comprehensive event handler cleanup to prevent memory leaks and improved cross-platform support with Meta key handling for macOS users.
Enhanced the system to always select the best available cache based on both blend area and crop, prioritizing exact matches. Prevented costly operations and live rendering during scaling for optimal performance and smooth user experience.
Redesigned the positioning system for the Blend Mode menu, inspired by the "Custom Output Area" logic. The menu now anchors precisely to the top-right corner of the viewport and stays in place during panning and zooming.
Added a clear first point distinction when drawing a custom shape: if the mouse cursor is near the beginning of a line (the shape can be closed), the first point is drawn in yellow and larger. This allows the user to see when they can close the shape with a single click. The code has been compiled and is ready to use. The functionality works as expected.
Replaces full-canvas mask operations with getMaskForOutputArea() for significant performance improvements when processing masks for the output area. Refines shape mask removal and application logic to ensure correct mask state when changing expansion values or custom shapes, including auto-removal and re-application of masks. Adds throttling to shape preview rendering for better UI responsiveness. Improves mask removal to eliminate antialiasing artifacts and updates SAM mask integration to use correct output area positioning.
Introduces helper methods to reduce code duplication and improve readability in CanvasInteractions. Mouse coordinate extraction, event prevention, zoom operations, drag-and-drop styling, and layer wheel transformations are now handled by dedicated methods. This refactor centralizes logic, making the codebase easier to maintain and extend.
Refactors how custom output area shapes interact with extensions, ensuring the shape's position and mask application remain consistent when extensions are toggled. Moves output area shape logic to CanvasInteractions, tracks original shape position, and updates all rendering, IO, and mask operations to use the correct coordinates. Improves mask chunk clearing and adds chunked mask application/removal for shape masks, ensuring correct behavior with expansion and feathering.
This update introduces a unified output area bounds system, allowing the output area to be extended in all directions independently of the custom shape. All mask and layer operations now reference outputAreaBounds, ensuring correct alignment and rendering. The mask tool, mask editor, and export logic have been refactored to use these bounds, and a new UI for output area extension with live preview and tooltips has been added. The code also improves logging and visualization of mask and output area boundaries.
Introduces a CustomShapeMenu UI component for managing custom output area shape masks, including options for auto-applying the mask, expansion/contraction, and feathering. Updates Canvas and MaskTool to support these new mask operations, and ensures the menu is shown or hidden based on shape presence. Adds distance transform-based algorithms for accurate mask expansion and feathering.
Always prevent the default browser context menu and stop event propagation on right-click interactions and custom menus. This ensures that only the application's custom context menus are shown and avoids interference from the browser's native context menu.
Introduces ShapeTool to allow users to define custom polygonal output areas by holding Shift+S and clicking to add points. The selected shape is used to crop and mask images and layers, and is visualized on the canvas. Updates Canvas, CanvasIO, CanvasInteractions, CanvasLayers, CanvasRenderer, and types to support shape-based output areas, including shape-aware import, export, and rendering logic.
Adds a window blur event listener to reset key states and interaction modes when the window loses focus. This prevents stuck key states and finalizes any in-progress cloning drags, improving interaction reliability.