     case doneDragging(atTime: NSDate)
 }
 
-private struct ObserveApplicationNotifications {
+class MouseStateKeeper {
+    public var state: MouseState
+    init() {
+        state = .pointing
+    }
+}
+
+private class ObserveApplicationNotifications {
     enum Error: Swift.Error {
         case failed
     }
 
     fileprivate let application: SIApplication
     fileprivate let windowManager: WindowManager
+    fileprivate let mouse: MouseStateKeeper
+
+    init(application app: SIApplication, windowManager wm: WindowManager) {
+        application = app
+        windowManager = wm
+        mouse = wm.mouseStateKeeper
+    }
 
     fileprivate func addObservers() -> Observable<Bool> {
         return _addObservers().retry(.exponentialDelayed(maxCount: 4, initial: 0.1, multiplier: 2))


final class WindowManager: NSObject {
    private var applications: [SIApplication] = []
    var windows: [SIWindow] = []
    fileprivate let userConfiguration: UserConfiguration


        let application = self.application
        let windowManager = self.windowManager

        let mouseEventsToWatch: NSEvent.EventTypeMask = [.leftMouseDown, .leftMouseUp, .leftMouseDragged]

        NSEvent.addGlobalMonitorForEvents(matching: mouseEventsToWatch) { anEvent in
            switch anEvent.type {
            case .leftMouseDown:
                self.mouse.state = .clicking
            case .leftMouseDragged:
                switch self.mouse.state {
                case .moving, .resizing:
                    () // ignore - we have what we need
                default:
                    self.mouse.state = .dragging
                }

            case .leftMouseUp:
                switch self.mouse.state {
                case .dragging:
                    // assume window move event will come shortly after
                    self.mouse.state = .doneDragging(atTime: NSDate())
                case let .moving(draggedWindow):
                    self.mouse.state = .pointing // flip state first to prevent race condition
                    self.swapDraggedWindowWithDropzone(draggedWindow)
                case let .resizing(resizedWindow):
                    self.mouse.state = .pointing
                case .doneDragging:
                    self.mouse.state = .doneDragging(atTime: NSDate()) // reset the clock I guess
                default:
                    self.mouse.state = .pointing
                }

            default: ()
