- Notifications
You must be signed in to change notification settings - Fork1
A Rust crate for subscribing and retrieving the current active space on Mac OS X
Schachte/space-monitor-rs
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Space Monitor is a Rust API for subscribing to real-time changes on Mac OS X to obtain the current activespace (virtual desktop) index.
Heavily inspired by the great work ofGeorge Christou and his Swift project -WhichSpace.
Check usage in theexamples directory
use std::thread;use macos_space_monitor::{MonitorEvent,SpaceMonitor};fnmain(){let(monitor, rx) =SpaceMonitor::new();let _monitoring_thread = thread::spawn(move ||{whileletOk(event) = rx.recv(){match event{MonitorEvent::SpaceChange(space) =>{println!("Space change detected! Active space is: {}", space);}}}}); monitor.start_listening();}
use macos_space_monitor::SpaceMonitor;fnmain(){let space =SpaceMonitor::get_current_space_number();println!("Current space: {}", space);}
This library was motivated by a fun project I am working on that deals with managing spaces in a more custom way on Mac OS X for more efficient space navigation. One of the core requirements when building space/window management tooling is to understandwhere you are within your display. This is a key crate I rely on to enable real-time lookups to map a virtual display ID to a space index.
If you don't know Rust or aren't using Rust and simply just want a binary you can invoke from your own code, you can build the example directly and embed the binary or add it to your$PATH
.
Event Listener Version:
- Build:
cargo build --release --example monitor
- Run:
./target/release/examples/monitor
- Build:
Adhoc Version:
- Build:
cargo build --release --example adhoc
- Run:
./target/release/examples/adhoc
- Build:
Surprisingly, obtaining the active virtual desktop index is a non-trivial task on Mac OS X and attempts in doing so have been breaking release after release as the method relies on undocumented Mac OS native APIs.
This method relies on a few key ingredients:
Core Graphics (CG)
- We use
CGSMainConnectionID
to get a connection to the main window server - The CGS (core graphics services) API is exploited to obtain this information
- We use
FFI (Foreign function interface)
- Bridge for us to call the C APIs from Rust
Cocoa
- Apple's native API for Mac OS apps
NSApplication
for background app- Handle system notifications
Objective-C
- Some message-passing invocations (
msg_send!
) - Used for receiving event notifications
- Some message-passing invocations (
Space monitor is essentially a Rust binding to access lower-level mac OS internal APIs in an easy and efficient way.
While you can occassionally deciper some esoteric plist files to derive the active screen viadefaults read com.apple.spaces SpacesDisplayConfiguration
, the contents are almost always incorrect and out of date, which makes it a non-starter for realtime change detection.
When I designed this crate, I wanted a minimal example I could iterate off of in Swift to simplify the migration into Rust since I'm not a Swift developer. Mostly just committing this for posterity, but you can find a much simpler implementation of this lib in Swift underneath the./swift directory. Once again, this is heavily inspired byWhichSpace, but wanted to remove all the boilerplate.
You can compile it via either of the following:
- ./swift/compile.sh
swiftc -o SpaceMonitor CurrentSpace-types.swift CurrentSpace-main.swift CurrentSpace-delegate.swift
Then just run:
./SpaceMonitor
As this crate relies on private, undocumented native Mac OS APIs internally, Ibelieve your app would be rejected from the Apple app store if this crate is used within your application. However, users can still install the application externally.
About
A Rust crate for subscribing and retrieving the current active space on Mac OS X
Topics
Resources
Uh oh!
There was an error while loading.Please reload this page.