# GreenshotMac A native, Apple-silicon macOS screenshot tool modelled on [Greenshot](https://github.com/greenshot/greenshot) for Windows. Written in Swift with AppKit, SwiftUI and ScreenCaptureKit — no Mono, no Wine, no .NET runtime. The original C# sources are kept in `reference-greenshot/` purely as the behavioural reference for the port. GreenshotMac is a rewrite, not a transpile: Greenshot's Win32 foundations (GDI+, WinForms, `RegisterHotKey`, the shell tray API) have no direct macOS counterparts. ## Requirements * macOS 14 (Sonoma) or later * Xcode 16 or later * Apple silicon (the target builds `arm64` only) ## Building ```bash open GreenshotMac.xcodeproj # then ⌘R # or xcodebuild -project GreenshotMac.xcodeproj -scheme GreenshotMac -configuration Release build ``` The target is configured for ad-hoc signing (`CODE_SIGN_IDENTITY = "-"`) so it builds without a developer account. Set your own team in *Signing & Capabilities* if you want a stable signature — macOS ties Screen Recording permission to the signature, so an ad-hoc build may ask for permission again after some rebuilds. On first launch macOS asks for **Screen Recording** permission (System Settings › Privacy & Security › Screen Recording). Nothing can be captured until it is granted. ## Using it GreenshotMac is a menu bar app (`LSUIElement`), so it has no Dock icon. The camera icon in the menu bar holds every command. Default global hotkeys — Greenshot's PrintScreen-based defaults don't exist on a Mac keyboard, so these use combinations macOS leaves free: | Action | Shortcut | | --- | --- | | Capture region | ⌥⇧⌘4 | | Capture full screen | ⌥⇧⌘3 | | Capture window | ⌥⇧⌘5 | | Capture last region | ⌥⇧⌘6 | All four are re-recordable in Preferences › Hotkeys. During a capture the desktop freezes under a dimmed overlay: drag to select a region, press **Space** to switch to window mode and click a window, **Esc** to cancel. A magnifier and a live pixel-size readout follow the cursor. ### Editor | Tool | Key | | --- | --- | | Select | V | | Rectangle / Ellipse | R / E | | Line / Arrow | L / A | | Freehand | F | | Text | T | | Highlight | H | | Obfuscate (pixelate or blur) | O | | Step counter | C | | Crop | K | Shift constrains shapes to squares/circles and lines to 45° steps. Arrow keys nudge the selection (⇧ for 10 px steps). ⌘Z / ⇧⌘Z undo and redo, including crops. ### Destinations After a capture the destination picker appears: a preview of what you grabbed, one button per destination, ⌘1…⌘9 to pick from the keyboard, Esc to discard, and "Always use this destination" to skip the dialog next time. The buttons default to Edit / Save to Disk / Copy to Clipboard / Send as Mail, matching Greenshot. The full destination set is clipboard, save with a filename pattern, Save As…, print, email, the macOS share sheet, and "open with". Set a destination as the default (skipping the picker) in Preferences › General, from the menu bar, or via the picker's checkbox. Filename patterns use Greenshot's syntax, ported verbatim: ``` ${capturetime:d"yyyy-MM-dd HH_mm_ss"}-${title} ``` Supported variables: `${capturetime}`, `${now}`, `${title}`, `${appname}`, `${user}`, `${hostname}`, `${mode}`, `${NUM}` (with `:d4` for zero padding), plus the `:t`, `:u`, `:l`, `:s`, `:r` parameters. ## How the port maps onto Greenshot | Greenshot (Windows) | GreenshotMac | | --- | --- | | `MainForm` + tray icon | `StatusMenuController` (`NSStatusItem`) | | `CaptureForm` | `CaptureOverlay` (one borderless window per display) | | `WindowCapture` / GDI+ | `CaptureEngine` (ScreenCaptureKit) | | `HotkeyControl` / `RegisterHotKey` | `HotkeyManager` (Carbon `RegisterEventHotKey`) | | `Surface` + `DrawableContainer` | `Surface` + `Element` hierarchy | | `ImageEditorForm` | `EditorWindowController` + `EditorCanvasView` | | `FilenameHelper` | `FilenamePattern` | | `ImageIO` | `ImageExporter` | | `IDestination` implementations | `Destinations` | | `SettingsForm` | `PreferencesView` (SwiftUI) | | `IniConfig` / `greenshot.ini` | `Configuration` (`UserDefaults`) | ## Not ported The plugin destinations (Imgur, Box, Dropbox, Confluence, Jira, Office, OCR, external command), the speech-bubble and SVG/emoji containers, `.gst` templates, and Greenshot's language packs. The destination layer is a single `switch` in `Destinations.swift`, so adding an upload target is a small, self-contained change. ## Licence Greenshot is GPL-3.0; this port keeps the same licence.