diff --git a/ScreenShader/main.swift b/ScreenShader/main.swift index 28e7990..19fca7f 100644 --- a/ScreenShader/main.swift +++ b/ScreenShader/main.swift @@ -48,13 +48,34 @@ class AppDelegate: NSObject, NSApplicationDelegate { /// Create overlay controllers for all enabled screens private func createOverlayControllers() { - // Remove existing controllers - overlayControllers.removeAll() + updateOverlayControllers() + } + + /// Update overlay controllers - only add/remove what changed + private func updateOverlayControllers() { + // Get current set of enabled display IDs + var enabledDisplayIDs = Set() + var screensByID: [CGDirectDisplayID: NSScreen] = [:] - // Create a controller for each enabled screen for screen in NSScreen.screens { let displayID = getDisplayID(for: screen) if config.isDisplayEnabled(displayID) { + enabledDisplayIDs.insert(displayID) + screensByID[displayID] = screen + } + } + + // Remove controllers for displays that are no longer enabled + let existingIDs = Set(overlayControllers.keys) + for displayID in existingIDs { + if !enabledDisplayIDs.contains(displayID) { + overlayControllers.removeValue(forKey: displayID) + } + } + + // Add controllers for newly enabled displays + for displayID in enabledDisplayIDs { + if overlayControllers[displayID] == nil, let screen = screensByID[displayID] { let controller = OverlayController( config: self.config, metrics: self.metrics, @@ -81,8 +102,8 @@ class AppDelegate: NSObject, NSApplicationDelegate { private func refreshConfig() { self.statusItem.button?.image = self.getMenuBarIcon() - // Recreate overlay controllers if display configuration changed - createOverlayControllers() + // Update overlay controllers - only adds/removes what changed + updateOverlayControllers() for controller in overlayControllers.values { controller.refreshConfig() diff --git a/ScreenShader/renderer.swift b/ScreenShader/renderer.swift index c448d01..11b064d 100644 --- a/ScreenShader/renderer.swift +++ b/ScreenShader/renderer.swift @@ -63,9 +63,17 @@ class SharedMetalResources { return backgroundTexture } + private var currentShaderPath: String? = nil + func setEffectSource(_ effectSource: String?, shaderPath: String? = nil) throws { + // Skip if shader hasn't changed + if effectSource == activeEffectSource && shaderPath == currentShaderPath { + return + } + // Reset preset self.shaderPreset = nil + self.currentShaderPath = shaderPath guard let effectSource = effectSource else { self.activeEffectSource = nil