Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions Loop/Core/WindowDragManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,56 @@ final class WindowDragManager {
private var leftMouseUpMonitor: PassiveEventMonitor?

private var determineDraggedWindowTask: Task<(), Never>?
private var accessibilityCheckerTask: Task<(), Never>?

private var currentMousePosition: CGPoint {
NSEvent.mouseLocation.flipY(screen: NSScreen.screens[0])
}

@MainActor
func addObservers() {
leftMouseDraggedMonitor = PassiveEventMonitor(
accessibilityCheckerTask = Task(priority: .background) { [weak self] in
for await status in AccessibilityManager.shared.stream(initial: true) {
guard let self, !Task.isCancelled else {
return
}

if status {
setupListeners()
} else {
removeListeners()
}
}
}
}

private func setupListeners() {
let leftMouseDraggedMonitor = PassiveEventMonitor(
events: [.leftMouseDragged],
callback: leftMouseDragged
)

leftMouseUpMonitor = PassiveEventMonitor(
let leftMouseUpMonitor = PassiveEventMonitor(
events: [.leftMouseUp],
callback: leftMouseUp
)

leftMouseDraggedMonitor!.start()
leftMouseUpMonitor!.start()
leftMouseDraggedMonitor.start()
leftMouseUpMonitor.start()

leftMouseDraggedMonitor.start()
leftMouseUpMonitor.start()

self.leftMouseDraggedMonitor = leftMouseDraggedMonitor
self.leftMouseUpMonitor = leftMouseUpMonitor
}

private func removeListeners() {
leftMouseUpMonitor?.stop()
leftMouseDraggedMonitor?.stop()

leftMouseUpMonitor = nil
leftMouseDraggedMonitor = nil
}

private func leftMouseDragged(event _: CGEvent) {
Expand Down
13 changes: 11 additions & 2 deletions Loop/Utilities/AccessibilityManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,10 @@ final class AccessibilityManager {
if getStatus() {
return true
}
resetAccessibility() // In case Loop is actually in the list, but the signature is different

// In case Loop is actually in the list, but the signature is different
resetAccessibility()
resetInputMonitoring()

let alert = NSAlert()
alert.messageText = .init(
Expand Down Expand Up @@ -125,10 +128,16 @@ final class AccessibilityManager {
}

/// Executes `/usr/bin/tccutil reset Accessibility <Bundle ID>`.
/// This fully removes any accessibility permissions the user may have previously granted to Loop.
/// This fully removes any accessibility permissions the user may have previously granted to anything with Loop's bundle ID.
private static func resetAccessibility() {
_ = try? Process.run(URL(filePath: "/usr/bin/tccutil"), arguments: ["reset", "Accessibility", Bundle.main.bundleID])
}

/// Executes `/usr/bin/tccutil reset ListenEvent <Bundle ID>`.
/// This fully removes any input monitoring permissions the user may have previously granted to anything with Loop's bundle ID.
private static func resetInputMonitoring() {
_ = try? Process.run(URL(filePath: "/usr/bin/tccutil"), arguments: ["reset", "ListenEvent", Bundle.main.bundleID])
}
}

private extension Notification.Name {
Expand Down