@@ -2,6 +2,10 @@ import AppKit
22import Common
33
44enum GlobalObserver {
5+ @MainActor private static var isInitialized = false
6+ @MainActor private static var notificationObserverTokens : [ NSObjectProtocol ] = [ ]
7+ @MainActor private static var eventMonitorTokens : [ Any ] = [ ]
8+
59 private static func onNotif( _ notification: Notification ) {
610 // Third line of defence against lock screen window. See: closedWindowsCache
711 // Second and third lines of defence are technically needed only to avoid potential flickering
@@ -69,15 +73,18 @@ enum GlobalObserver {
6973
7074 @MainActor
7175 static func initObserver( ) {
76+ guard !isInitialized else { return }
77+ isInitialized = true
78+
7279 let nc = NSWorkspace . shared. notificationCenter
73- nc. addObserver ( forName: NSWorkspace . didLaunchApplicationNotification, object: nil , queue: . main, using: onNotif)
74- nc. addObserver ( forName: NSWorkspace . didActivateApplicationNotification, object: nil , queue: . main, using: onNotif)
75- nc. addObserver ( forName: NSWorkspace . didHideApplicationNotification, object: nil , queue: . main, using: onHideApp)
76- nc. addObserver ( forName: NSWorkspace . didUnhideApplicationNotification, object: nil , queue: . main, using: onNotif)
77- nc. addObserver ( forName: NSWorkspace . activeSpaceDidChangeNotification, object: nil , queue: . main, using: onNotif)
78- nc. addObserver ( forName: NSWorkspace . didTerminateApplicationNotification, object: nil , queue: . main, using: onNotif)
80+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . didLaunchApplicationNotification, object: nil , queue: . main, using: onNotif) )
81+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . didActivateApplicationNotification, object: nil , queue: . main, using: onNotif) )
82+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . didHideApplicationNotification, object: nil , queue: . main, using: onHideApp) )
83+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . didUnhideApplicationNotification, object: nil , queue: . main, using: onNotif) )
84+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . activeSpaceDidChangeNotification, object: nil , queue: . main, using: onNotif) )
85+ notificationObserverTokens . append ( nc. addObserver ( forName: NSWorkspace . didTerminateApplicationNotification, object: nil , queue: . main, using: onNotif) )
7986
80- NSEvent . addGlobalMonitorForEvents ( matching: . leftMouseUp) { _ in
87+ retainEventMonitor ( NSEvent . addGlobalMonitorForEvents ( matching: . leftMouseUp) { _ in
8188 // todo reduce number of refreshSession in the callback
8289 // resetManipulatedWithMouseIfPossible might call its own refreshSession
8390 // The end of the callback calls refreshSession
@@ -98,38 +105,43 @@ enum GlobalObserver {
98105 scheduleRefreshSession ( . globalObserverLeftMouseUp)
99106 }
100107 }
101- }
108+ } )
102109
103- NSEvent . addGlobalMonitorForEvents ( matching: . leftMouseDragged) { _ in
110+ retainEventMonitor ( NSEvent . addGlobalMonitorForEvents ( matching: . leftMouseDragged) { _ in
104111 Task { @MainActor in
105112 refreshPendingWindowDragIntentFromGlobalMouseDrag ( )
106113 }
107- }
114+ } )
108115
109116 let pointerActivityMask : NSEvent . EventTypeMask = [
110117 . leftMouseDown, . rightMouseDown, . otherMouseDown,
111118 . leftMouseDragged, . rightMouseDragged, . otherMouseDragged,
112119 . scrollWheel,
113120 ]
114- NSEvent . addGlobalMonitorForEvents ( matching: pointerActivityMask, handler: onPointerActivity)
115- NSEvent . addLocalMonitorForEvents ( matching: pointerActivityMask) { event in
121+ retainEventMonitor ( NSEvent . addGlobalMonitorForEvents ( matching: pointerActivityMask, handler: onPointerActivity) )
122+ retainEventMonitor ( NSEvent . addLocalMonitorForEvents ( matching: pointerActivityMask) { event in
116123 onPointerActivity ( event)
117124 return event
118- }
125+ } )
119126
120- NSEvent . addGlobalMonitorForEvents ( matching: . flagsChanged, handler: onFlagsChanged)
121- NSEvent . addLocalMonitorForEvents ( matching: . flagsChanged) { event in
127+ retainEventMonitor ( NSEvent . addGlobalMonitorForEvents ( matching: . flagsChanged, handler: onFlagsChanged) )
128+ retainEventMonitor ( NSEvent . addLocalMonitorForEvents ( matching: . flagsChanged) { event in
122129 onFlagsChanged ( event)
123130 return event
124- }
131+ } )
125132
126- NSEvent . addGlobalMonitorForEvents ( matching: . keyDown, handler: onKeyDown)
127- NSEvent . addLocalMonitorForEvents ( matching: . keyDown) { event in
133+ retainEventMonitor ( NSEvent . addGlobalMonitorForEvents ( matching: . keyDown, handler: onKeyDown) )
134+ retainEventMonitor ( NSEvent . addLocalMonitorForEvents ( matching: . keyDown) { event in
128135 onKeyDown ( event)
129136 if event. modifierFlags. contains ( . control) , event. keyCode == 34 {
130137 return nil // consume the event
131138 }
132139 return event
133- }
140+ } )
141+ }
142+
143+ @MainActor private static func retainEventMonitor( _ monitor: Any ? ) {
144+ guard let monitor else { return }
145+ eventMonitorTokens. append ( monitor)
134146 }
135147}
0 commit comments