Allow annotations to start outside the canvas - #108
Conversation
ad1f316 to
58227d6
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Chrome hit-testing and incremental marker preview repainting have unresolved correctness issues.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Enables annotations to begin in the workspace surrounding a screenshot and expand the canvas.
Changes:
- Adds off-canvas creation rules and previews while restricting source-based tools.
- Adds smoke coverage for creation, undo, and boundary behavior.
- Documents the expanded workspace behavior.
File summaries
| File | Description |
|---|---|
src/editor.cpp |
Implements off-canvas creation and rendering. |
src/editor.hpp |
Declares workspace hit-testing helpers. |
tests/editor-smoke.cpp |
Tests off-canvas workflows and restrictions. |
README.md |
Documents canvas growth behavior. |
Review details
Suppressed comments (1)
src/editor.cpp:6297
- The marker ghost can now be painted outside
editImageRect(), butpointerMotionRegion()still adds the marker’s actual bounds only wheneditImageRect().contains(point)(line 4162). Mouse movement uses partial repaint regions, so a large or zoomed marker in the new workspace can be clipped or leave stale pixels; this smoke test’sgrab()forces a full repaint and masks the problem. Use the samecanStartAnnotationAt(point)predicate in marker damage calculation.
const bool markerPreview = tool_ == Tool::Marker && !dragging_ &&
canStartAnnotationAt(cursor_) &&
!pointerGrabsLayer();
const bool markerPreviewOutsideCanvas =
markerPreview && !image.contains(cursor_);
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| bool CaptureEditor::canStartAnnotationAt(const QPointF &position) const { | ||
| if (requiresSourcePixels(tool_)) | ||
| return sourceFrameWidgetRect().contains(position); | ||
| if (editImageRect().contains(position)) | ||
| return true; | ||
| if (canvasBoundaryMode_ == CanvasBoundaryMode::Image || | ||
| !supportsOffCanvasCreation(tool_) || | ||
| !annotationWorkspaceRect().contains(position)) | ||
| return false; | ||
| // Popovers overlap the content band. Their buttons are handled before the | ||
| // workspace, while their padding must remain chrome rather than canvas. | ||
| if ((colorPaletteOpen_ && colorPaletteRect().contains(position)) || | ||
| (customColorPickerOpen_ && customColorPanelRect().contains(position)) || | ||
| (shapeMenuOpen_ && shapeMenuRect().contains(position)) || | ||
| (textSizeMenuOpen_ && textSizePanelRect().contains(position))) | ||
| return false; | ||
| return true; | ||
| } |
There was a problem hiding this comment.
🟡 Changes recommended
An in-flight highlighter probe can incorrectly affect an off-canvas stroke.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Balanced
| } else if (canStartAnnotationAt(cursor_)) { | ||
| scheduleHighlighterProbe(toUnclampedAnnotationPoint(cursor_)); | ||
| } else { | ||
| clearHighlighterPreview(); | ||
| } |
There was a problem hiding this comment.
🟡 Changes recommended
Right-side off-canvas text is constrained to a 48-pixel editor and becomes clipped while typing.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Balanced
| case CaptureEditor::Tool::Marker: | ||
| case CaptureEditor::Tool::Rectangle: | ||
| case CaptureEditor::Tool::Ellipse: | ||
| case CaptureEditor::Tool::Text: |
Summary
Test plan
make check