Skip to content
Open
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
38 changes: 28 additions & 10 deletions PiHoleStats/Controllers/MenuController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class MenuController: NSObject {
private lazy var navigationController = NavigationController(preferences: preferences, piholeDataProvider: dataProvider)
private lazy var dataProvider = PiholeDataProvider(piholes: Pihole.restoreAll())
private lazy var summaryViewController = SummaryViewController(preferences: preferences, piHoleDataProvider: dataProvider, navigationController: navigationController)
private var eventMonitor: EventMonitor?
private var globalEventMonitor: EventMonitor?
private var localEventMonitor: EventMonitor?
private var eventCancellable: AnyCancellable?
private var statusPreferenceCancellable: AnyCancellable?
private var statusCancellable: AnyCancellable?
Expand All @@ -36,7 +37,7 @@ class MenuController: NSObject {
public func setup() {
updateButton()
popover.contentViewController = summaryViewController
setupEventMonitor()
setupEventMonitors()
dataProvider.startPolling()
dataProvider.updatePollingMode(.background)
updateButtonStatus()
Expand All @@ -46,9 +47,11 @@ class MenuController: NSObject {
private func setupCancellables() {
eventCancellable = preferences.$keepPopoverPanelOpen.receive(on: DispatchQueue.main).sink { [weak self] keepPopoverOpen in
if keepPopoverOpen {
self?.eventMonitor?.stop()
self?.globalEventMonitor?.stop()
self?.localEventMonitor?.stop()
} else {
self?.eventMonitor?.start()
self?.globalEventMonitor?.start()
self?.localEventMonitor?.start()
}
}
statusPreferenceCancellable = preferences.$displayStatusColorWhenPiholeIsOffline.receive(on: DispatchQueue.main).sink { [weak self] _ in
Expand All @@ -60,17 +63,30 @@ class MenuController: NSObject {
}
}

private func setupEventMonitor() {
eventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown]) { [weak self] event in
private func setupEventMonitors() {
globalEventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown], scope: .global) { [weak self] event in
if let strongSelf = self, strongSelf.popover.isShown {
strongSelf.closePopover(sender: event)
}
}

localEventMonitor = EventMonitor(mask: [.leftMouseDown, .rightMouseDown], scope: .local) { [weak self] event in
guard let self = self else { return }

let popoverWindow = self.popover.contentViewController?.view.window

if event?.window != popoverWindow && self.popover.isShown {
self.closePopover(sender: event)
}
}
}

private func destroyEventMonitor() {
eventMonitor?.stop()
eventMonitor = nil
globalEventMonitor?.stop()
globalEventMonitor = nil

localEventMonitor?.stop()
localEventMonitor = nil
}

private func updateButtonStatus() {
Expand Down Expand Up @@ -113,7 +129,8 @@ class MenuController: NSObject {
private func showPopover(sender: Any?) {
guard let button = statusItem.button else { return }
if !preferences.keepPopoverPanelOpen {
eventMonitor?.start()
globalEventMonitor?.start()
localEventMonitor?.start()
}

popover.show(
Expand All @@ -126,7 +143,8 @@ class MenuController: NSObject {

private func closePopover(sender: Any?) {
popover.performClose(sender)
eventMonitor?.stop()
globalEventMonitor?.stop()
localEventMonitor?.stop()
dataProvider.updatePollingMode(.background)

}
Expand Down
21 changes: 19 additions & 2 deletions PiHoleStats/Util/EventMonitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,20 @@ import Cocoa
import os.log

public class EventMonitor {
public enum EventScope {
case global
case local
}

private let log = Logger().osLog(describing: EventMonitor.self)
private var monitor: Any?
private let mask: NSEvent.EventTypeMask
private let scope: EventScope
private let handler: (NSEvent?) -> Void

public init(mask: NSEvent.EventTypeMask, handler: @escaping (NSEvent?) -> Void) {
public init(mask: NSEvent.EventTypeMask, scope: EventScope, handler: @escaping (NSEvent?) -> Void) {
self.mask = mask
self.scope = scope
self.handler = handler
os_log("Event monitor init", log: self.log, type: .debug)
}
Expand All @@ -55,7 +62,17 @@ public class EventMonitor {
return
}
os_log("Event monitor start", log: self.log, type: .debug)
monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler)

switch scope {
case .global:
monitor = NSEvent.addGlobalMonitorForEvents(matching: mask, handler: handler)
case .local:
monitor = NSEvent.addLocalMonitorForEvents(matching: mask) { event in
self.handler(event)

return event
}
}
}

public func stop() {
Expand Down