From 3e423a14f40f0633358d8de1657c9d6fb7f4da34 Mon Sep 17 00:00:00 2001 From: lwouis Date: Sat, 23 Nov 2024 09:09:26 +0100 Subject: [PATCH] refactor: observe mouse events from main thread: simpler/faster --- src/logic/BackgroundWork.swift | 5 +---- src/logic/events/MouseEvents.swift | 19 +++++++------------ 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/logic/BackgroundWork.swift b/src/logic/BackgroundWork.swift index dc7ef4f9..1daf97b1 100644 --- a/src/logic/BackgroundWork.swift +++ b/src/logic/BackgroundWork.swift @@ -7,7 +7,6 @@ class BackgroundWork { static var axCallsQueue: DispatchQueue! static var crashReportsQueue: DispatchQueue! static var accessibilityEventsThread: BackgroundThreadWithRunLoop! - static var mouseEventsThread: BackgroundThreadWithRunLoop! static var keyboardEventsThread: BackgroundThreadWithRunLoop! static var systemPermissionsThread: BackgroundThreadWithRunLoop! static var repeatingKeyThread: BackgroundThreadWithRunLoop! @@ -26,9 +25,7 @@ class BackgroundWork { axCallsQueue = DispatchQueue.globalConcurrent("axCallsQueue", .userInteractive) // we observe app and windows notifications. They arrive on this thread, and are handled off the main thread initially accessibilityEventsThread = BackgroundThreadWithRunLoop("accessibilityEventsThread", .userInteractive) - // we observe mouse clicks when thumbnailsPanel is open. They arrive on this thread, and are handled off the main thread initially - mouseEventsThread = BackgroundThreadWithRunLoop("mouseEventsThread", .userInteractive) - // some instances of events can be handled off the main thread; maybe not worth moving to a background thread + // we listen to as any keyboard events as possible on a background thread, as it's more available/reliable than the main thread keyboardEventsThread = BackgroundThreadWithRunLoop("keyboardEventsThread", .userInteractive) // not 100% sure this shouldn't be on the main-thread; it doesn't do anything except dispatch to main.async repeatingKeyThread = BackgroundThreadWithRunLoop("repeatingKeyThread", .userInteractive) diff --git a/src/logic/events/MouseEvents.swift b/src/logic/events/MouseEvents.swift index 5f8e50ff..b287f0d0 100644 --- a/src/logic/events/MouseEvents.swift +++ b/src/logic/events/MouseEvents.swift @@ -3,7 +3,6 @@ import Carbon.HIToolbox.Events fileprivate var eventTap: CFMachPort! fileprivate var shouldBeEnabled: Bool! -fileprivate var isPointerInsideUi: Bool! class MouseEvents { static func observe() { @@ -20,7 +19,7 @@ class MouseEvents { private func observe_() { let eventMask = [CGEventType.leftMouseDown, CGEventType.leftMouseUp].reduce(CGEventMask(0), { $0 | (1 << $1.rawValue) }) - // CGEvent.tapCreate returns null if ensureAccessibilityCheckboxIsChecked() didn't pass + // CGEvent.tapCreate returns nil if ensureAccessibilityCheckboxIsChecked() didn't pass eventTap = CGEvent.tapCreate( tap: .cgSessionEventTap, place: .headInsertEventTap, @@ -31,7 +30,7 @@ private func observe_() { if let eventTap = eventTap { MouseEvents.toggle(false) let runLoopSource = CFMachPortCreateRunLoopSource(nil, eventTap, 0) - CFRunLoopAddSource(BackgroundWork.mouseEventsThread.runLoop, runLoopSource, .commonModes) + CFRunLoopAddSource(CFRunLoopGetMain(), runLoopSource, .commonModes) } else { App.app.restart() } @@ -39,14 +38,12 @@ private func observe_() { private let handleEvent: CGEventTapCallBack = { _, type, cgEvent, _ in if type == .leftMouseDown { - isPointerInsideUi_() - if !isPointerInsideUi { + if !isPointerInsideUi() { return nil // focused app won't receive the event } } else if type == .leftMouseUp && cgEvent.getIntegerValueField(.mouseEventClickState) >= 1 { - isPointerInsideUi_() - if !isPointerInsideUi { - DispatchQueue.main.async { App.app.hideUi() } + if !isPointerInsideUi() { + App.app.hideUi() return nil // focused app won't receive the event } } else if (type == .tapDisabledByUserInput || type == .tapDisabledByTimeout) && shouldBeEnabled { @@ -55,8 +52,6 @@ private let handleEvent: CGEventTapCallBack = { _, type, cgEvent, _ in return Unmanaged.passUnretained(cgEvent) // focused app will receive the event } -private func isPointerInsideUi_() { - DispatchQueue.main.sync { - isPointerInsideUi = App.app.thumbnailsPanel.contentLayoutRect.contains(App.app.thumbnailsPanel.mouseLocationOutsideOfEventStream) - } +private func isPointerInsideUi() -> Bool { + return App.app.thumbnailsPanel.contentLayoutRect.contains(App.app.thumbnailsPanel.mouseLocationOutsideOfEventStream) }