mirror of
https://github.com/FBukovina/Atoll.git
synced 2026-10-27 15:14:33 +00:00
BugFix: Multiple object creation
This commit is contained in:
parent
1a45d4e7f4
commit
f4bcb96906
8 changed files with 202 additions and 33 deletions
|
|
@ -112,9 +112,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
// Cancel any pending window size updates
|
// Cancel any pending window size updates
|
||||||
windowSizeUpdateWorkItem?.cancel()
|
windowSizeUpdateWorkItem?.cancel()
|
||||||
|
|
||||||
|
print("🚪 Application terminating - ensuring system HUD is restored...")
|
||||||
|
|
||||||
// Re-enable system HUD on app termination
|
// Re-enable system HUD on app termination
|
||||||
SystemOSDManager.enableSystemHUD()
|
SystemOSDManager.enableSystemHUD()
|
||||||
|
|
||||||
|
// Give it time to complete
|
||||||
|
usleep(500000) // 500ms
|
||||||
|
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ struct DynamicIslandHeader: View {
|
||||||
@ObservedObject var batteryModel = BatteryStatusViewModel.shared
|
@ObservedObject var batteryModel = BatteryStatusViewModel.shared
|
||||||
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
||||||
@ObservedObject var clipboardManager = ClipboardManager.shared
|
@ObservedObject var clipboardManager = ClipboardManager.shared
|
||||||
@StateObject var tvm = TrayDrop.shared
|
@ObservedObject var tvm = TrayDrop.shared
|
||||||
@State private var showClipboardPopover = false
|
@State private var showClipboardPopover = false
|
||||||
@State private var showColorPickerPopover = false
|
@State private var showColorPickerPopover = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import SwiftUI
|
||||||
|
|
||||||
struct NotchShelfView: View {
|
struct NotchShelfView: View {
|
||||||
@EnvironmentObject var vm: DynamicIslandViewModel
|
@EnvironmentObject var vm: DynamicIslandViewModel
|
||||||
@StateObject var tvm = TrayDrop.shared
|
@ObservedObject var tvm = TrayDrop.shared
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ struct DropItemView: View {
|
||||||
let item: TrayDrop.DropItem
|
let item: TrayDrop.DropItem
|
||||||
@EnvironmentObject var vm: DynamicIslandViewModel
|
@EnvironmentObject var vm: DynamicIslandViewModel
|
||||||
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
@ObservedObject var coordinator = DynamicIslandViewCoordinator.shared
|
||||||
@StateObject var tvm = TrayDrop.shared
|
@ObservedObject var tvm = TrayDrop.shared
|
||||||
|
|
||||||
@State var hover = false
|
@State var hover = false
|
||||||
|
|
||||||
|
|
|
||||||
83
DynamicIsland/helpers/SystemHUDDebugger.swift
Normal file
83
DynamicIsland/helpers/SystemHUDDebugger.swift
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
//
|
||||||
|
// SystemHUDDebugger.swift
|
||||||
|
// DynamicIsland
|
||||||
|
//
|
||||||
|
// Debug utility for System HUD functionality
|
||||||
|
// Created by GitHub Copilot on 06/09/25.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
class SystemHUDDebugger {
|
||||||
|
|
||||||
|
/// Test system HUD functionality and print status
|
||||||
|
public static func testSystemHUD() {
|
||||||
|
print("\n🔍 === System HUD Debug Report ===")
|
||||||
|
|
||||||
|
// Check current OSDUIHelper status
|
||||||
|
let isRunning = SystemOSDManager.isOSDUIHelperRunning()
|
||||||
|
print("📊 OSDUIHelper Status: \(isRunning ? "✅ Running" : "❌ Not running")")
|
||||||
|
|
||||||
|
// Test disable
|
||||||
|
print("🔇 Testing disable...")
|
||||||
|
SystemOSDManager.disableSystemHUD()
|
||||||
|
|
||||||
|
// Wait and check
|
||||||
|
usleep(500000)
|
||||||
|
let isRunningAfterDisable = SystemOSDManager.isOSDUIHelperRunning()
|
||||||
|
print("📊 After disable: \(isRunningAfterDisable ? "✅ Running (stopped)" : "❌ Not running")")
|
||||||
|
|
||||||
|
// Test enable
|
||||||
|
print("🔊 Testing re-enable...")
|
||||||
|
SystemOSDManager.enableSystemHUD()
|
||||||
|
|
||||||
|
// Wait and check
|
||||||
|
usleep(1000000)
|
||||||
|
let isRunningAfterEnable = SystemOSDManager.isOSDUIHelperRunning()
|
||||||
|
print("📊 After re-enable: \(isRunningAfterEnable ? "✅ Running" : "❌ Not running")")
|
||||||
|
|
||||||
|
print("🔍 === End Debug Report ===\n")
|
||||||
|
|
||||||
|
if !isRunningAfterEnable {
|
||||||
|
print("⚠️ WARNING: System HUD may not be working properly!")
|
||||||
|
print("💡 Try pressing volume keys to test system HUD functionality")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Force restart OSDUIHelper using multiple methods
|
||||||
|
public static func forceRestartOSDUIHelper() {
|
||||||
|
print("🔄 Force restarting OSDUIHelper...")
|
||||||
|
|
||||||
|
// Method 1: Kill and kickstart
|
||||||
|
SystemOSDManager.enableSystemHUD()
|
||||||
|
|
||||||
|
// Method 2: Try launchctl bootstrap (more aggressive)
|
||||||
|
do {
|
||||||
|
let bootstrap = Process()
|
||||||
|
bootstrap.executableURL = URL(fileURLWithPath: "/bin/launchctl")
|
||||||
|
bootstrap.arguments = ["bootstrap", "gui/\(getuid())", "/System/Library/LaunchAgents/com.apple.OSDUIHelper.plist"]
|
||||||
|
try bootstrap.run()
|
||||||
|
bootstrap.waitUntilExit()
|
||||||
|
print("✅ Bootstrap method completed")
|
||||||
|
} catch {
|
||||||
|
print("❌ Bootstrap method failed: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method 3: Try direct service restart
|
||||||
|
do {
|
||||||
|
let restart = Process()
|
||||||
|
restart.executableURL = URL(fileURLWithPath: "/bin/launchctl")
|
||||||
|
restart.arguments = ["restart", "gui/\(getuid())/com.apple.OSDUIHelper"]
|
||||||
|
try restart.run()
|
||||||
|
restart.waitUntilExit()
|
||||||
|
print("✅ Restart method completed")
|
||||||
|
} catch {
|
||||||
|
print("❌ Restart method failed: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check final status
|
||||||
|
usleep(1000000)
|
||||||
|
let finalStatus = SystemOSDManager.isOSDUIHelperRunning()
|
||||||
|
print("📊 Final OSDUIHelper status: \(finalStatus ? "✅ Running" : "❌ Not running")")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,16 +10,13 @@ import Cocoa
|
||||||
import Foundation
|
import Foundation
|
||||||
import Defaults
|
import Defaults
|
||||||
|
|
||||||
class SystemChangesObserver: ObservableObject {
|
class SystemChangesObserver {
|
||||||
private var oldVolume: Float
|
private var oldVolume: Float
|
||||||
private var oldMuted: Bool
|
private var oldMuted: Bool
|
||||||
private var oldBrightness: Float = 0
|
private var oldBrightness: Float = 0
|
||||||
|
|
||||||
private weak var coordinator: DynamicIslandViewCoordinator?
|
private weak var coordinator: DynamicIslandViewCoordinator?
|
||||||
|
private var timer: Timer?
|
||||||
@Default(.enableSystemHUD) var enableSystemHUD
|
|
||||||
@Default(.enableVolumeHUD) var enableVolumeHUD
|
|
||||||
@Default(.enableBrightnessHUD) var enableBrightnessHUD
|
|
||||||
|
|
||||||
init(coordinator: DynamicIslandViewCoordinator) {
|
init(coordinator: DynamicIslandViewCoordinator) {
|
||||||
self.coordinator = coordinator
|
self.coordinator = coordinator
|
||||||
|
|
@ -34,18 +31,18 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
func startObserving() {
|
func startObserving() {
|
||||||
guard enableSystemHUD else { return }
|
guard Defaults[.enableSystemHUD] else { return }
|
||||||
|
|
||||||
createObservers()
|
createObservers()
|
||||||
createTimerForContinuousChangesCheck(with: 0.2)
|
createTimerForContinuousChangesCheck(with: 0.2)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createTimerForContinuousChangesCheck(with seconds: TimeInterval) {
|
private func createTimerForContinuousChangesCheck(with seconds: TimeInterval) {
|
||||||
let timer = Timer(
|
timer = Timer(
|
||||||
timeInterval: seconds, target: self, selector: #selector(checkChanges), userInfo: nil,
|
timeInterval: seconds, target: self, selector: #selector(checkChanges), userInfo: nil,
|
||||||
repeats: true)
|
repeats: true)
|
||||||
let mainLoop = RunLoop.main
|
let mainLoop = RunLoop.main
|
||||||
mainLoop.add(timer, forMode: .common)
|
mainLoop.add(timer!, forMode: .common)
|
||||||
}
|
}
|
||||||
|
|
||||||
private func createObservers() {
|
private func createObservers() {
|
||||||
|
|
@ -63,7 +60,7 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func showVolumeHUD() {
|
@objc func showVolumeHUD() {
|
||||||
guard enableSystemHUD && enableVolumeHUD else { return }
|
guard Defaults[.enableSystemHUD] && Defaults[.enableVolumeHUD] else { return }
|
||||||
|
|
||||||
if oldVolume == 0.0 || oldVolume == 1.0 {
|
if oldVolume == 0.0 || oldVolume == 1.0 {
|
||||||
sendVolumeNotification(value: oldVolume)
|
sendVolumeNotification(value: oldVolume)
|
||||||
|
|
@ -72,7 +69,7 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func showBrightnessHUD() {
|
@objc func showBrightnessHUD() {
|
||||||
guard enableSystemHUD && enableBrightnessHUD else { return }
|
guard Defaults[.enableSystemHUD] && Defaults[.enableBrightnessHUD] else { return }
|
||||||
|
|
||||||
if oldBrightness == 0.0 || oldBrightness == 1.0 {
|
if oldBrightness == 0.0 || oldBrightness == 1.0 {
|
||||||
sendBrightnessNotification(value: oldBrightness)
|
sendBrightnessNotification(value: oldBrightness)
|
||||||
|
|
@ -81,7 +78,7 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc func checkChanges() {
|
@objc func checkChanges() {
|
||||||
guard enableSystemHUD else { return }
|
guard Defaults[.enableSystemHUD] else { return }
|
||||||
|
|
||||||
checkBrightnessChanges()
|
checkBrightnessChanges()
|
||||||
checkVolumeChanges()
|
checkVolumeChanges()
|
||||||
|
|
@ -93,7 +90,7 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkVolumeChanges() {
|
private func checkVolumeChanges() {
|
||||||
guard enableVolumeHUD else { return }
|
guard Defaults[.enableVolumeHUD] else { return }
|
||||||
|
|
||||||
let newVolume = SystemVolumeManager.getOutputVolume()
|
let newVolume = SystemVolumeManager.getOutputVolume()
|
||||||
let newMuted = SystemVolumeManager.isMuted()
|
let newMuted = SystemVolumeManager.isMuted()
|
||||||
|
|
@ -110,7 +107,7 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func checkBrightnessChanges() {
|
private func checkBrightnessChanges() {
|
||||||
guard enableBrightnessHUD else { return }
|
guard Defaults[.enableBrightnessHUD] else { return }
|
||||||
|
|
||||||
if NSScreen.screens.count == 0 {
|
if NSScreen.screens.count == 0 {
|
||||||
return
|
return
|
||||||
|
|
@ -148,6 +145,12 @@ class SystemChangesObserver: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
stopObserving()
|
||||||
|
}
|
||||||
|
|
||||||
|
func stopObserving() {
|
||||||
|
timer?.invalidate()
|
||||||
|
timer = nil
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -7,31 +7,38 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import Defaults
|
import Defaults
|
||||||
|
import Combine
|
||||||
|
|
||||||
class SystemHUDManager: ObservableObject {
|
class SystemHUDManager {
|
||||||
static let shared = SystemHUDManager()
|
static let shared = SystemHUDManager()
|
||||||
|
|
||||||
private var changesObserver: SystemChangesObserver?
|
private var changesObserver: SystemChangesObserver?
|
||||||
private weak var coordinator: DynamicIslandViewCoordinator?
|
private weak var coordinator: DynamicIslandViewCoordinator?
|
||||||
|
|
||||||
@Default(.enableSystemHUD) var enableSystemHUD {
|
private init() {
|
||||||
didSet {
|
// Set up observer for settings changes
|
||||||
Task { @MainActor in
|
setupSettingsObserver()
|
||||||
if enableSystemHUD {
|
|
||||||
await startSystemHUD()
|
|
||||||
} else {
|
|
||||||
await stopSystemHUD()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private init() {}
|
private func setupSettingsObserver() {
|
||||||
|
// Use Defaults publisher instead of @Default property wrapper
|
||||||
|
Defaults.publisher(.enableSystemHUD, options: []).sink { [weak self] change in
|
||||||
|
Task { @MainActor in
|
||||||
|
if change.newValue {
|
||||||
|
await self?.startSystemHUD()
|
||||||
|
} else {
|
||||||
|
await self?.stopSystemHUD()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
func setup(coordinator: DynamicIslandViewCoordinator) {
|
func setup(coordinator: DynamicIslandViewCoordinator) {
|
||||||
self.coordinator = coordinator
|
self.coordinator = coordinator
|
||||||
|
|
||||||
if enableSystemHUD {
|
if Defaults[.enableSystemHUD] {
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
await startSystemHUD()
|
await startSystemHUD()
|
||||||
}
|
}
|
||||||
|
|
@ -56,6 +63,7 @@ class SystemHUDManager: ObservableObject {
|
||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private func stopSystemHUD() async {
|
private func stopSystemHUD() async {
|
||||||
|
changesObserver?.stopObserving()
|
||||||
changesObserver = nil
|
changesObserver = nil
|
||||||
|
|
||||||
// Re-enable system HUD
|
// Re-enable system HUD
|
||||||
|
|
@ -65,18 +73,36 @@ class SystemHUDManager: ObservableObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
private func disableSystemHUD() {
|
private func disableSystemHUD() {
|
||||||
|
print("🔇 Disabling system HUD (OSDUIHelper running: \(SystemOSDManager.isOSDUIHelperRunning()))")
|
||||||
// Disable the system HUD using SystemOSDManager
|
// Disable the system HUD using SystemOSDManager
|
||||||
SystemOSDManager.disableSystemHUD()
|
SystemOSDManager.disableSystemHUD()
|
||||||
}
|
}
|
||||||
|
|
||||||
private func enableOriginalSystemHUD() {
|
private func enableOriginalSystemHUD() {
|
||||||
|
print("🔊 Re-enabling system HUD (OSDUIHelper running: \(SystemOSDManager.isOSDUIHelperRunning()))")
|
||||||
// Re-enable the system HUD using SystemOSDManager
|
// Re-enable the system HUD using SystemOSDManager
|
||||||
SystemOSDManager.enableSystemHUD()
|
SystemOSDManager.enableSystemHUD()
|
||||||
|
|
||||||
|
// Verify it's working after a short delay
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||||
|
let isRunning = SystemOSDManager.isOSDUIHelperRunning()
|
||||||
|
print("🔍 OSDUIHelper status after re-enable: \(isRunning ? "✅ Running" : "❌ Not running")")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
|
print("🧹 SystemHUDManager deinitializing - ensuring system HUD is restored")
|
||||||
|
cancellables.removeAll()
|
||||||
Task { @MainActor in
|
Task { @MainActor in
|
||||||
await stopSystemHUD()
|
await stopSystemHUD()
|
||||||
}
|
}
|
||||||
|
// Also call the emergency restore as backup
|
||||||
|
SystemHUDDebugger.forceRestartOSDUIHelper()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Emergency restore function - call this if system HUD is not working
|
||||||
|
public static func emergencyRestoreSystemHUD() {
|
||||||
|
print("🚨 Emergency system HUD restore initiated")
|
||||||
|
SystemHUDDebugger.forceRestartOSDUIHelper()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -14,13 +14,41 @@ class SystemOSDManager {
|
||||||
/// Re-enables the system HUD by restarting OSDUIHelper
|
/// Re-enables the system HUD by restarting OSDUIHelper
|
||||||
public static func enableSystemHUD() {
|
public static func enableSystemHUD() {
|
||||||
do {
|
do {
|
||||||
let task = Process()
|
// First, stop any existing OSDUIHelper process
|
||||||
task.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
|
let stopTask = Process()
|
||||||
task.arguments = ["-9", "OSDUIHelper"]
|
stopTask.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
|
||||||
try task.run()
|
stopTask.arguments = ["-9", "OSDUIHelper"]
|
||||||
print("System HUD re-enabled")
|
try stopTask.run()
|
||||||
|
stopTask.waitUntilExit()
|
||||||
|
|
||||||
|
// Small delay to ensure process is fully stopped
|
||||||
|
usleep(200000) // 200ms
|
||||||
|
|
||||||
|
// Then kickstart it again to ensure it's running properly
|
||||||
|
let kickstart = Process()
|
||||||
|
kickstart.executableURL = URL(fileURLWithPath: "/bin/launchctl")
|
||||||
|
kickstart.arguments = ["kickstart", "gui/\(getuid())/com.apple.OSDUIHelper"]
|
||||||
|
try kickstart.run()
|
||||||
|
kickstart.waitUntilExit()
|
||||||
|
|
||||||
|
// Additional delay to ensure service is fully started
|
||||||
|
usleep(300000) // 300ms
|
||||||
|
|
||||||
|
print("✅ System HUD re-enabled")
|
||||||
} catch {
|
} catch {
|
||||||
NSLog("Error while trying to re-enable OSDUIHelper. \(error)")
|
NSLog("❌ Error while trying to re-enable OSDUIHelper: \(error)")
|
||||||
|
|
||||||
|
// Fallback: Try to restart the service using launchctl load
|
||||||
|
do {
|
||||||
|
let fallbackTask = Process()
|
||||||
|
fallbackTask.executableURL = URL(fileURLWithPath: "/bin/launchctl")
|
||||||
|
fallbackTask.arguments = ["load", "-w", "/System/Library/LaunchAgents/com.apple.OSDUIHelper.plist"]
|
||||||
|
try fallbackTask.run()
|
||||||
|
fallbackTask.waitUntilExit()
|
||||||
|
print("✅ System HUD re-enabled via fallback method")
|
||||||
|
} catch {
|
||||||
|
NSLog("❌ Fallback method also failed: \(error)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,9 +67,33 @@ class SystemOSDManager {
|
||||||
task.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
|
task.executableURL = URL(fileURLWithPath: "/usr/bin/killall")
|
||||||
task.arguments = ["-STOP", "OSDUIHelper"]
|
task.arguments = ["-STOP", "OSDUIHelper"]
|
||||||
try task.run()
|
try task.run()
|
||||||
print("System HUD disabled")
|
task.waitUntilExit()
|
||||||
|
|
||||||
|
print("✅ System HUD disabled")
|
||||||
} catch {
|
} catch {
|
||||||
NSLog("Error while trying to hide OSDUIHelper. Please create an issue on GitHub. Error: \(error)")
|
NSLog("❌ Error while trying to hide OSDUIHelper: \(error)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if OSDUIHelper is currently running
|
||||||
|
public static func isOSDUIHelperRunning() -> Bool {
|
||||||
|
let task = Process()
|
||||||
|
task.executableURL = URL(fileURLWithPath: "/usr/bin/pgrep")
|
||||||
|
task.arguments = ["OSDUIHelper"]
|
||||||
|
|
||||||
|
let pipe = Pipe()
|
||||||
|
task.standardOutput = pipe
|
||||||
|
|
||||||
|
do {
|
||||||
|
try task.run()
|
||||||
|
task.waitUntilExit()
|
||||||
|
|
||||||
|
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
||||||
|
let output = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
|
||||||
|
return task.terminationStatus == 0 && !output!.isEmpty
|
||||||
|
} catch {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue