Window picks now capture via ScreenCaptureKit's desktopIndependentWindow
filter, so the image carries the app's actual rounded-corner alpha
instead of a fixed 10pt mask that let the desktop show through on apps
with larger radii. Falls back to crop+mask when the window is not in the
shareable content.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
A leftover heuristic skipped any window matching its screen's dimensions,
which made window detection silently fail on secondary monitors where the
working window is typically maximized.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
A tap-disabled callback force-unwrapped the tap port, which could crash
the app mid-capture (no result window, dead hotkey). Guard it and log
re-enables. Result window display is now logged with the image size.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The first capture used to start the overlay and the system permission
prompt at once, making both uninteractive. begin() now requires
Accessibility up front, shows an alert with a direct link to the setting,
and only starts capturing once granted. Captures log their display,
backing scale, and rect mapping for diagnosing multi-display offsets.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Panel event delivery is unreliable on macOS 26 (clicks pass through even
with the app active and the panel key). The selection flow is now driven
by a CGEventTap that sees and consumes mouse events system-wide: hover
highlights windows, clicks capture them (rounded), drags marquee-select,
Esc cancels. Requires Accessibility permission, prompted on first use;
falls back to panel events when unavailable.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
A stale copy surviving an update keeps its own hotkey and overlays on
screen, silently eating every click meant for the new instance (matching
the empty session logs). New copies now force-terminate older instances,
and the first window scan logs the topmost on-screen windows so anything
covering the overlays is visible in diagnostics.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The local probe confirmed activation is asynchronous on macOS 26:
isActive flips on a later runloop tick, so overlays shown in the same
tick as activate() belong to a still-inactive app and misses clicks.
Delay overlay creation by a tick and log the activation state at show
time.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The session log showed active=false after every activation attempt on
macOS 26: cooperative activation is denied for LSUIElement apps, and an
inactive app's panels let clicks fall through to the windows below.
Remove .nonactivatingPanel so showing the overlay activates the app
(previous app focus is restored after capture as before).
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Cooperative NSApp.activate() can silently fail for LSUIElement apps,
leaving the app inactive so overlay clicks pass through to windows below.
Force activation with ignoringOtherApps on all OS versions. Session logs
now also append to /tmp/kapture-debug.log so they survive relaunches, and
the first window-scan result is always logged.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
OverlayView now logs window tracking counts, hover changes, and
mouseDown/Up branch decisions into a session log that Copy Diagnostics
includes along with the app version, so capture failures on machines we
cannot access directly can be diagnosed from a pasted report.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Window frames are now converted to AppKit space once at detection time, so
hover highlighting and picking work on every display. A click is only
treated as a drag after 4pt of movement, so clicking a detected window
captures it instead of passing a stray marquee. Redact is now a standalone
tool (Select/Draw/Redact) with its own toolbar hints instead of a toggle
inside the draw bar.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Window detection was broken by wrong CG-to-AppKit coordinate conversion
of the cursor and highlight rects — both now go through the same
cgToAppKit mapping. The draw toolbar gains a Pen/Redact toggle: redact
drags cover content with a solid black bar (participates in undo/redo
and export like pen strokes).
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
brew tap without a URL resolves to GitHub, where the tap no longer exists;
the full Gitea URL is required.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Hovering during selection now highlights the window under the cursor;
clicking captures it with a rounded-corner alpha mask matching macOS
window chrome. Dragging still switches to manual marquee selection.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The strokes were stored in top-left image coordinates but drawn into an
AppKit CGContext with a bottom-left origin, so exports came out mirrored
and offset. Flip Y in the context before stroking so annotations land
where they were drawn.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Each drawn stroke now stores its own width and color, so changing the
thickness slider no longer retroactively resizes existing strokes. The
Clear button is back in the draw toolbar.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The color picker, undo/redo, and clear eraser now live in the dedicated
draw top bar instead of the main toolbar, keeping the primary actions
(Copy/Save/Get Text) uncluttered. Keyboard shortcuts (⌘Z/⌘⇧Z) remain.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
When drawing is enabled a dedicated top bar shows a thickness slider,
color picker, and undo/redo buttons (⌘Z / ⌘⇧Z). Strokes render and export
with the chosen width and color.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
A compact ColorPicker appears next to the Draw button when drawing is
enabled; strokes render and export in the chosen color (defaults to
system red).
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The captured CGImage has a top-left origin, while the crop rect was
computed in SCDisplay space (bottom-left). Flip Y within the display's
bounds when converting to pixel coordinates so the crop lands exactly
where the user selected.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The new CGImage.cropping path expects a top-left pixel rect; the previous
CGContext redraw had implicitly flipped Y. Keep the existing SCDisplay-space
conversion so the crop matches the selected region.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The screenshot window now supports toggling a pen to draw annotations
that are flattened into copied and saved images. Captures are also
cropped with a pixel-exact CGImage.cropping instead of a CGContext
redraw, removing residual blur on retina displays.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Restyles the window with a cleaner layout: icon-based toolbar buttons
(Copy/Save/Get All Text, highlighted OCR Selection action), a bottom status
bar with progress indicator and contextual hints, monospaced text tab, and
a divider separating chrome from content.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The result window now works like a screenshot tool: drag on the image to
select a region, then click Get Selection Text to OCR only that area
(full-image OCR stays as Get All Text). Selection is rendered in image
coordinates so it stays accurate at any window size.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The first ScreenCaptureKit Y-flip used the wrong reference edges, shifting
cropped selections on displays below the main screen. Convert each selection
per-display as scY = appKitY - NSScreen.maxY + SCDisplay.maxY, which
matches both the main and secondary displays.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
ScreenCaptureKit uses a flipped Y axis relative to AppKit NSScreen frames,
so selections on a display below the main screen produced out-of-bounds
crop rects and "Capture failed". Convert the selection into SCDisplay space
using the matching NSScreen's top edge before cropping.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Prints each NSScreen's frame/backing scale/CG display ID and each
SCDisplay's frame/point size, and copies it to the clipboard, so
secondary-display capture failures can be debugged from the menu bar.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
SCDisplay.width is in points, not pixels: the previous fix sent point
counts to SCStreamConfiguration, producing blurry main-screen captures and
failed secondary-screen captures. Multiply by the backing scale factor of
the screen containing the selection (defaulting to 1x, never forcing 2x).
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The 1.1.2 retina fix overrode the stream width from the display's pixel
dimensions, which made captures on secondary monitors come out at the
wrong scale or offset. Restore requesting the display's native pixel
resolution and keep the crop scale derived from the actual returned image,
plus guard against out-of-bounds crop rects.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Full-res retina captures are downscaled to fit the window; nearest-neighbor
made them look chunky. Use high-quality interpolation when shrinking, keep
pixel-crisp rendering only when upscaling small selections.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The ScreenCaptureKit stream was sized in points at 1x scale, so retina
displays produced half-resolution captures that appeared pixelated.
Request backingScale x pixels and derive the crop scale from the actual
captured image dimensions.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
The result image was upscaled with interpolated smoothing, making small
captures look low-res. Disable interpolation so pixels stay 1:1 sharp.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
release.sh now submits the zip to Apple's notary via notarytool, staples
the ticket, and repackages, so users no longer hit Gatekeeper warnings.
build-app.sh signs Developer ID builds with the hardened runtime and
unlocks the login keychain to avoid transient signing errors. The private
API key (.p8) is gitignored.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731
Users can now launch Kapture at login, keep multiple screenshot windows open
at once, and copy a screenshot to the clipboard. Builds sign with a Developer
ID identity when present, falling back to the ad-hoc self-signed key, so
Screen Recording permission survives rebuilds.
💘 Generated with Crush
Assisted-by: Crush:deepseek-v4-flash-0731