Skip to content

Swift wrapper around CGEvent and the Event Tap set of APIs.

License

Notifications You must be signed in to change notification settings

philptr/EventTapCore

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EventTapCore

EventTapCore is a Swift module that provides a wrapper around CGEvent and related types, as well as a high-level, type-safe interface for monitoring and handling system events on macOS. It wraps the low-level Core Graphics event tap APIs in a modern, Swift-friendly way with support for async streams and a SwiftUI integration.

Features

  • Rich event metadata and field information
  • Type-safe event monitoring with async/await support
  • SwiftUI-ready with @Observable integration

Installation

Swift Package Manager

Add the following to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/philptr/EventTapCore.git", from: "1.0.0")
]

Basic Usage

Simple Event Monitoring

import EventTapCore

let tap = EventTap(tapLocation: .session, tapPlacement: .head)

try tap.startMonitoring { type, event in
    print("Received event of type \(type): \(event).")
}

Using Async Streams

import EventTapCore

let eventStream = EventTap.events(at: .session, placement: .head)

for await event in eventStream {
    print("Received event: \(event).")
}

SwiftUI Integration with EventTapCoordinator

import EventTapCore

@main
struct MyApp: App {
    @State private var coordinator = EventTapCoordinator()
    
    var body: some Scene {
        WindowGroup {
            EventList(events: coordinator.events)
                .onAppear {
                    coordinator.startMonitoring()
                }
        }
    }
}

Interface

EventTap

The primary class for creating and managing event taps, as well as receiving callbacks. It provides both closure-based and async stream APIs for event monitoring.

EventTapCoordinator

A higher level, SwiftUI-friendly coordinator that manages event monitoring and state, providing:

  • Observable event collection;
  • Automatic event throttling;
  • Thread-safe event handling;
  • Lifecycle management.

Event

A structure that represents a system event with rich metadata including timestamp, location, event type, and associated field values.

Security and Permissions

EventTapCore requires Input Monitoring permissions to monitor events from other applications. This requirement is imposed by the low-level API. In your application, you might want to include an experience to allow the user to grant your application access.

// Check if we have permission to monitor events.
if CGPreflightListenEventAccess() {
    // Start monitoring...
} else {
    // Request permission.
    CGRequestListenEventAccess()
    
    // Offer to take the user to System Settings...
}

Best Practices

  1. Always handle tap lifecycle properly:

    // Start monitoring when needed
    try tap.startMonitoring(...)
    
    // Stop monitoring when done
    tap.stopMonitoring()
  2. Consider event throttling, especially when displaying events in the UI or altering state:

    coordinator.startMonitoring(throttledFor: .milliseconds(500))
  3. Check for Input Monitoring permissions before starting.

Requirements

  • macOS 11.0 or later
  • Swift 6.0 or later

Debugging Tools

For debugging and monitoring system events, check out EventTapper - a collection of ready-made debugging utilities built on EventTapCore.

EventTapper

About

Swift wrapper around CGEvent and the Event Tap set of APIs.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages