Skip to content

Commit 9d69376

Browse files
committed
Keep key listeners alive
1 parent dfb55cc commit 9d69376

File tree

1 file changed

+31
-19
lines changed

1 file changed

+31
-19
lines changed

Sources/AppBundle/GlobalObserver.swift

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@ import AppKit
22
import Common
33

44
enum 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

Comments
 (0)