When the Code Was Right All Along

In my WindowPin write-up, I casually suggested two things I’d do differently if I were starting over: replace the CGEvent tap keyboard shortcut handler with something SwiftUI-native, and switch from timer-based screenshots to ScreenCaptureKit’s streaming API.

I went back and actually investigated both. The results were humbling.

The Shortcut Handler

The current implementation uses a CGEvent tap — a low-level system event interceptor that catches keyboard events before they reach any application. It requires a C-compatible callback function, module-level global state, accessibility permissions with a retry loop, and about 200 lines of code that nobody would call elegant.

The “improvement” I had in mind was NSEvent.addGlobalMonitorForEvents — a higher-level AppKit API that’s cleaner, shorter, and doesn’t need C callbacks. It would cut the code roughly in half.

The problem: it doesn’t work as well. NSEvent.addGlobalMonitorForEvents fires after the event has already been delivered to the frontmost application. It can miss events. It can fire late. It can be silently consumed by another app before WindowPin ever sees it. For a global shortcut that needs to work reliably regardless of what’s in focus, this is disqualifying.

CGEvent tap intercepts at the system level, before dispatch. That’s why it needs the ugly C callback — and that’s why it works. The complexity isn’t accidental; it’s the minimum required for reliable global shortcuts on macOS.

Verdict: The 200 lines stay. They’re there for a reason.

The Capture Loop

WindowPin captures window content by calling SCScreenshotManager.captureImage() on a timer. Once per second by default, configurable up to 30 FPS. Each tick takes a single screenshot, converts it to an NSImage, and updates the overlay. Simple, predictable, easy to reason about.

The “improvement” was to switch to SCStream — ScreenCaptureKit’s streaming API, which continuously pushes frames through a callback. More modern. More architecturally correct. The kind of thing you’d reach for if you were building a screen recorder.

Three problems:

SCStream doesn’t let you set a frame rate. It captures at whatever rate the source produces. To get 1 FPS from a 60 FPS stream, you’d have to receive all 60 frames and throw away 59 of them. That’s not more efficient — it’s dramatically less efficient.

Changing capture rate requires restarting the stream. With the timer approach, changing from 1 FPS to 10 FPS is a one-liner: update the timer interval. With SCStream, you’d stop the stream, reconfigure it, and restart it — potentially causing a visible glitch in the overlay.

At low frame rates, polling is cheaper than streaming. A continuous SCStream maintains an open connection to the screen capture server. A timer that fires once per second and takes a single screenshot uses fewer resources by a wide margin. WindowPin’s default capture rate is 1 FPS. The streaming API is optimised for 30-60 FPS video capture, not lazy polling of a mostly-static window.

Verdict: Timer plus captureImage() is the right tool. SCStream would be the right tool if WindowPin were a screen recorder. It isn’t.

The Lesson

It’s easy to look at working code and imagine improvements. Fancier APIs, newer patterns, less boilerplate. But “newer” and “cleaner” aren’t the same as “better.” The right question isn’t “could this use a more modern API?” — it’s “does this solve the problem reliably and efficiently?”

In both cases, the answer was already yes. The code I wanted to improve was doing exactly what it should, in the way it should, for exactly the right reasons. The only thing wrong with it was that it didn’t look as elegant as I thought it could.

Sometimes the best refactor is the one you don’t do.