Skip to content

Add Capture Previous Screen Region - #19

Open
nsathya2010 wants to merge 9 commits into
microsoft:mainfrom
nsathya2010:feat/last-capture-region
Open

Add Capture Previous Screen Region#19
nsathya2010 wants to merge 9 commits into
microsoft:mainfrom
nsathya2010:feat/last-capture-region

Conversation

@nsathya2010

@nsathya2010 nsathya2010 commented Jul 13, 2026

Copy link
Copy Markdown

Use Case

Many users repeatedly capture the same area of the screen—for example:

  1. Monitoring logs or terminal output
  2. Capturing application windows during development
  3. Recording UI changes during testing
  4. Taking periodic screenshots for documentation
  5. Currently, the region must be selected manually for every capture, even if it is identical to the previous one.

Proposed Solution

Add a new command (and optionally a configurable keyboard shortcut) named "Capture Previous Region" that:

  1. Remembers the last successfully captured region.
  2. Reuses that region for subsequent captures without displaying the selection UI.
  3. Updates the stored region whenever the user performs a new manual region selection.

@nsathya2010 nsathya2010 changed the title updated read me Add Capture Previous Screen Region Jul 13, 2026
@nsathya2010
nsathya2010 marked this pull request as draft July 13, 2026 04:45
@nsathya2010

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

@nsathya2010
nsathya2010 marked this pull request as ready for review July 15, 2026 11:09
@nsathya2010

Copy link
Copy Markdown
Author

It closes #18 !

I have build the code and tested the code. The previous capture works just fine.

@MarioHewardt

Copy link
Copy Markdown
Contributor

Hi - thanks for the contribution! We'd like to see if the keyboard shortcut for this can be a variant of the existing snip shortcut (CTRL-6)....for example CTRL-SHIFT-OPTION 6.

Copilot AI review requested due to automatic review settings July 17, 2026 04:58

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new “Capture Previous Region” command to reuse the last successful region snip (without re-opening the drag selection UI), including a configurable hotkey, menu entry, and documentation updates.

Changes:

  • Introduces a new app command (snipPreviousRegion) wired through hotkey handling, mode coordination, and app menu/controller actions.
  • Tracks the last successful region selection for reuse (idle-mode snips via SnipController, zoomed-overlay snips via ZoomCanvasView).
  • Adds settings persistence + UI for configuring the new hotkey, and updates README/help text to document defaults and behavior.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Sources/ZoomItMacCore/Settings/SettingsWindowController.swift Adds UI + conflict handling for the new “Capture Previous Region” hotkey and updates help text.
Sources/ZoomItMacCore/Settings/SettingsStore.swift Persists the new hotkey settings and defines defaults.
Sources/ZoomItMacCore/Overlay/ZoomCanvasView.swift Remembers and reuses the previous region within the overlay; refactors region snip execution.
Sources/ZoomItMacCore/Overlay/OverlayWindowController.swift Exposes an overlay-level “capture previous region” entry point.
Sources/ZoomItMacCore/Hotkeys/HotkeyService.swift Registers two hotkeys (copy vs save) for “Capture Previous Region” and maps them to a new command.
Sources/ZoomItMacCore/Core/ModeCoordinator.swift Routes the new command and adds support for reusing the previous region in both idle and overlay modes.
Sources/ZoomItMacCore/Core/AppCommand.swift Adds the new command case.
Sources/ZoomItMacCore/Capture/SnipController.swift Stores the previous selection and implements “capture previous” without UI.
Sources/ZoomItMacCore/App/AppDelegate.swift Adds a menu item for “Capture Previous Region”.
Sources/ZoomItMacCore/App/AppController.swift Handles menu action by dispatching the new command.
README.md Documents the new default hotkeys and describes the feature.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/ZoomItMacCore/Hotkeys/HotkeyService.swift Outdated
Comment thread Sources/ZoomItMacCore/Settings/SettingsWindowController.swift
Comment thread Sources/ZoomItMacCore/Settings/SettingsWindowController.swift
Comment thread Sources/ZoomItMacCore/Capture/SnipController.swift Outdated
Comment on lines +284 to +287
guard let display = displayManager.activeDisplay() else {
finish()
return true
}
Comment on lines +879 to +895
guard rect.width >= 3, rect.height >= 3, let full = captureViewportImage() else {
return false
}

let scale = window?.backingScaleFactor ?? capturedFrame.display.scaleFactor
let pixelRect = CGRect(
x: rect.minX * scale,
y: rect.minY * scale,
width: rect.width * scale,
height: rect.height * scale
).integral

guard let cropped = full.cropping(to: pixelRect) else {
return false
}

previousRegionRect = rect
@nsathya2010

Copy link
Copy Markdown
Author

Hi - thanks for the contribution! We'd like to see if the keyboard shortcut for this can be a variant of the existing snip shortcut (CTRL-6)....for example CTRL-SHIFT-OPTION 6.

Thanks for the suggestions. Update the shortcut keys.

image

Copilot AI review requested due to automatic review settings July 17, 2026 05:32
@nsathya2010
nsathya2010 force-pushed the feat/last-capture-region branch from a38146c to f18d9a0 Compare July 17, 2026 05:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment on lines +878 to +895
private func performRegionSnip(rect: CGRect, action: SnipAction) -> Bool {
guard rect.width >= 3, rect.height >= 3, let full = captureViewportImage() else {
return false
}

let scale = window?.backingScaleFactor ?? capturedFrame.display.scaleFactor
let pixelRect = CGRect(
x: rect.minX * scale,
y: rect.minY * scale,
width: rect.width * scale,
height: rect.height * scale
).integral

guard let cropped = full.cropping(to: pixelRect) else {
return false
}

previousRegionRect = rect
Comment thread Sources/ZoomItMacCore/Capture/SnipController.swift
Comment on lines +682 to +685
private func conflictsWithSnipPrevious(code: Int, modifiers: UInt) -> Bool {
settings.snipPreviousHotKeyCode != 0 &&
code == settings.snipPreviousHotKeyCode && modifiers == settings.snipPreviousHotKeyModifiers
}
Copilot AI review requested due to automatic review settings July 17, 2026 05:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Comment on lines +284 to +287
guard let display = displayManager.activeDisplay() else {
finish()
return true
}
Comment on lines +291 to +295
let frame = try await captureService.captureDisplay(display)
let rect = previousSelection.rectForCurrentDisplay(frame.display)
_ = self.handleSelection(rect, in: frame)
self.finish()
} catch {
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Copilot AI review requested due to automatic review settings July 17, 2026 05:50

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated 3 comments.

Comment on lines +682 to +685
private func conflictsWithSnipPrevious(code: Int, modifiers: UInt) -> Bool {
settings.snipPreviousHotKeyCode != 0 &&
code == settings.snipPreviousHotKeyCode && modifiers == settings.snipPreviousHotKeyModifiers
}
Comment thread Sources/ZoomItMacCore/Capture/SnipController.swift Outdated
Comment on lines +414 to +423
if reusePreviousRegion {
isSnipping = true
let started = snipController.capturePrevious(action: action) { [weak self] in
self?.isSnipping = false
}
if !started {
isSnipping = false
NSSound.beep()
}
return
Fix for rectangle

Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Copilot AI review requested due to automatic review settings July 24, 2026 02:13

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 11 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (3)

Sources/ZoomItMacCore/Settings/SettingsWindowController.swift:685

  • conflictsWithSnipPrevious only checks the base modifiers, but HotkeyService registers two global hotkeys for this command (base and base-with-Shift-toggled). This allows other shortcuts to be set to the save-variant combination without being flagged as a conflict, potentially resulting in duplicate registrations and ambiguous behavior.
    private func conflictsWithSnipPrevious(code: Int, modifiers: UInt) -> Bool {
        settings.snipPreviousHotKeyCode != 0 &&
            code == settings.snipPreviousHotKeyCode && modifiers == settings.snipPreviousHotKeyModifiers
    }

Sources/ZoomItMacCore/Capture/SnipController.swift:285

  • capturePrevious always captures displayManager.activeDisplay() (cursor location) even though the previous selection stores the original displayID. If the user moves the cursor to a different monitor, “Capture Previous Region” can capture from the wrong display. Prefer capturing the previous display when it still exists, and fall back to the active display only if that display is no longer available.
        guard let display = displayManager.activeDisplay() else {
            NSSound.beep()
            finish()
            return true
        }

Sources/ZoomItMacCore/Capture/SnipController.swift:292

  • The result of handleSelection is ignored when reusing the previous region. If scaling/intersection/cropping fails, the action will silently do nothing (no copy/save) with no feedback. Consider beeping when handleSelection returns false so the user knows the capture failed.
                let frame = try await captureService.captureDisplay(display)
                let rect = previousSelection.rectForCurrentDisplay(frame.display)
                _ = self.handleSelection(rect, in: frame)
                self.finish()

Copilot AI review requested due to automatic review settings July 24, 2026 02:32

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (4)

Sources/ZoomItMacCore/Settings/SettingsWindowController.swift:670

  • When recording the “Capture Previous Region” hotkey, conflicts are only checked against the base shortcuts for Snip/Record/DemoType/Panorama. Those commands all register a second variant with Shift toggled, so users can currently set “Capture Previous Region” to (for example) the existing “Snip region to file” shortcut without a conflict being detected, leading to duplicate/failed hotkey registrations at runtime. Also, this hotkey’s help text says “Hold Shift … to save”, but recording currently allows Shift in the base modifiers, which inverts/ambiguous behavior because HotkeyService uses XOR to toggle Shift.
        case .snipPrevious:
            if conflictsWithZoom(code: newCode, modifiers: newModifiers) ||
                conflictsWithDraw(code: newCode, modifiers: newModifiers) ||
                conflictsWithLive(code: newCode, modifiers: newModifiers) ||
                conflictsWithBreak(code: newCode, modifiers: newModifiers) ||

Sources/ZoomItMacCore/Settings/SettingsWindowController.swift:757

  • conflictsWithSnipPrevious only checks the base modifiers, but HotkeyService registers two hotkeys for this command (base and base-with-Shift-toggled). This lets another command be recorded to the “save” variant without any conflict being flagged.
    private func conflictsWithSnipPrevious(code: Int, modifiers: UInt) -> Bool {
        settings.snipPreviousHotKeyCode != 0 &&
            code == settings.snipPreviousHotKeyCode && modifiers == settings.snipPreviousHotKeyModifiers
    }

Sources/ZoomItMacCore/Capture/SnipController.swift:299

  • capturePrevious stores the display ID in PreviousSelection, but then always captures displayManager.activeDisplay(). If the cursor is on a different monitor when the hotkey is pressed, the “previous region” is applied to the wrong display, which doesn’t match the expected ‘repeat the last capture area’.
        guard let display = displayManager.activeDisplay() else {
            NSSound.beep()
            finish()
            return true
        }

Sources/ZoomItMacCore/Capture/SnipController.swift:306

  • In capturePrevious, a failed reuse (e.g. the scaled/clipped rect becomes too small or ends up outside the current display bounds) is currently silent because the return value of handleSelection is ignored. That leaves the user with no feedback when nothing is captured.
                let rect = previousSelection.rectForCurrentDisplay(frame.display)
                _ = self.handleSelection(rect, in: frame)
                self.finish()

Comment on lines +206 to +217
func rectForCurrentDisplay(_ display: DisplayDescriptor) -> CGRect {
guard displaySize.width > 0, displaySize.height > 0 else { return rect }

let widthScale = display.frame.width / displaySize.width
let heightScale = display.frame.height / displaySize.height
return CGRect(
x: rect.minX * widthScale,
y: rect.minY * heightScale,
width: rect.width * widthScale,
height: rect.height * heightScale
)
}
Comment on lines +55 to +57
@objc func capturePreviousRegion() {
modeCoordinator.handle(.snipPreviousRegion(save: false))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants