-
Notifications
You must be signed in to change notification settings - Fork 66
Architecture
State, Application, Window, Screen, and Space are the public API classes.
State holds the top-level Swindler state: all the running applications, the screens, and the spaces we know about. Application keeps track of the windows of an application and which one is focused, and Window tracks all the attributes of a particular window (position, size, and title).
There are lots of relationships here (a window belongs to an application, and is on a particular screen). Holding an instance of any of these classes gives you access to the entire State through strong references.
These are really just thin wrappers around the delegates.
Most of the functionality (and all of the platform-specific stuff) is contained in delegates, like OSXStateDelegate, OSXApplicationDelegate, and so on. This is done for a couple reasons:
- While having strong reference cycles in the public API makes it easy to use, Swindler shouldn't have reference cycles internally. Therefore all internal state is kept in delegates, which hold weak references to their parents. That way when the framework user lets go of all of their public API classes, everything gets freed.
- It would be nice to offer a fake implementation of Swindler for framework users to write tests against. Using delegates we can swap out the implementation without requiring users to change their code.
There should be clean separation between the public API and delegate layers. Right now some of the public API classes are leaking into the delegates, which I intend to fix (#3).
The delegates still don't actually touch system-level APIs, otherwise we couldn't unit test them. Instead, protocols are defined around every API we need to use, and the delegates are generic so we can plug in stub implementations of those APIs in testing.
Property and WriteableProperty are public classes that support interacting with properties of system objects (like Application.isHidden
and Window.position
). They define the asynchronous API for writing, and encapsulate all the logic of writing and refreshing property values, emitting events when one is defined for a property.
Properties are created with a PropertyDelegate which defines the underlying operations needed to read and write to a property. A commonly used one is AXPropertyDelegate, which reads and writes to an AXUIElement attribute.