From 79bd48166e8ad9b5c06d32c399fc2bf0ebb7064f Mon Sep 17 00:00:00 2001 From: JoniVR Date: Sun, 16 Dec 2018 16:29:21 +0100 Subject: [PATCH] refactor --- MonitorControl.xcodeproj/project.pbxproj | 86 +---- MonitorControl/AppDelegate.swift | 424 +++++++++++------------ 2 files changed, 223 insertions(+), 287 deletions(-) diff --git a/MonitorControl.xcodeproj/project.pbxproj b/MonitorControl.xcodeproj/project.pbxproj index 077426f..470f5a8 100644 --- a/MonitorControl.xcodeproj/project.pbxproj +++ b/MonitorControl.xcodeproj/project.pbxproj @@ -7,13 +7,13 @@ objects = { /* Begin PBXBuildFile section */ + 2E3C2647A29DDCAA1F2D4E29 /* Pods_MonitorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */; }; 56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */; }; 56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB01D9A4016007BCDC5 /* Assets.xcassets */; }; 56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB21D9A4016007BCDC5 /* MainMenu.xib */; }; 6C33119021C58BF600971151 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 6C33118921C58BF500971151 /* README.md */; }; 6C33119221C58BF600971151 /* ddcctl.sh in Resources */ = {isa = PBXBuildFile; fileRef = 6C33118C21C58BF500971151 /* ddcctl.sh */; }; 6C33119521C58BF600971151 /* DDC.c in Sources */ = {isa = PBXBuildFile; fileRef = 6C33118F21C58BF600971151 /* DDC.c */; }; - 9A19D3B73485870616B6D4E0 /* Pods_MonitorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */; }; F03A8DF21FFBAA6F0034DC27 /* Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = F03A8DF11FFBAA6F0034DC27 /* Display.swift */; }; F0445D3820023E710025AE82 /* MainPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0445D3720023E710025AE82 /* MainPrefsViewController.swift */; }; F0445D3D200254FA0025AE82 /* KeysPrefsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0445D3B200254FA0025AE82 /* KeysPrefsViewController.swift */; }; @@ -44,13 +44,13 @@ /* Begin PBXFileReference section */ 31E16D90527EBD3F8A12BE0B /* Pods-MonitorControl.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonitorControl.release.xcconfig"; path = "Pods/Target Support Files/Pods-MonitorControl/Pods-MonitorControl.release.xcconfig"; sourceTree = ""; }; - 398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MonitorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 42B61ABC1D7907131330228A /* Pods-MonitorControl.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MonitorControl.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MonitorControl/Pods-MonitorControl.debug.xcconfig"; sourceTree = ""; }; 56754EAB1D9A4016007BCDC5 /* MonitorControl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonitorControl.app; sourceTree = BUILT_PRODUCTS_DIR; }; 56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AppDelegate.swift; sourceTree = ""; }; 56754EB01D9A4016007BCDC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 56754EB31D9A4016007BCDC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 56754EB51D9A4016007BCDC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MonitorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 6C33118921C58BF500971151 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 6C33118B21C58BF500971151 /* DDC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DDC.h; sourceTree = ""; }; 6C33118C21C58BF500971151 /* ddcctl.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ddcctl.sh; sourceTree = ""; }; @@ -77,17 +77,6 @@ F091C9C31F6EB8720096FD65 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; F091C9C41F6EBA5A0096FD65 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; F0A987D61F77B290009B603D /* OSD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OSD.framework; sourceTree = ""; }; - F0A987DA1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = ""; }; - F0A987DC1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; - F0A987DD1F77B404009B603D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - F0A987DF1F77B404009B603D /* SliderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandler.swift; sourceTree = ""; }; - F0A987E11F77B404009B603D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - F0A987E21F77B404009B603D /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = ""; }; - F0A987E31F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/MainMenu.strings; sourceTree = ""; }; - F0A987E41F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; - F0A987E51F77B404009B603D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - F0A987E61F77B404009B603D /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = ""; }; - F0A987E71F77B404009B603D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -96,7 +85,7 @@ buildActionMask = 2147483647; files = ( F0A987E81F77B40E009B603D /* OSD.framework in Frameworks */, - 9A19D3B73485870616B6D4E0 /* Pods_MonitorControl.framework in Frameworks */, + 2E3C2647A29DDCAA1F2D4E29 /* Pods_MonitorControl.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -131,8 +120,8 @@ 55359E321E2737EC002671BC /* ddcctl */, F06792E8200A73460066C438 /* MonitorControlHelper */, 56754EAC1D9A4016007BCDC5 /* Products */, - F0A987D71F77B404009B603D /* Frameworks */, EFFC2F3E35BEC9ACFA754137 /* Pods */, + 8ABFD04A9742F18299723076 /* Frameworks */, ); sourceTree = ""; }; @@ -162,6 +151,14 @@ path = MonitorControl; sourceTree = ""; }; + 8ABFD04A9742F18299723076 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 65A9B356B917FAB6583F09A6 /* Pods_MonitorControl.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; EFFC2F3E35BEC9ACFA754137 /* Pods */ = { isa = PBXGroup; children = ( @@ -201,39 +198,6 @@ path = Objects; sourceTree = ""; }; - F0A987D71F77B404009B603D /* Frameworks */ = { - isa = PBXGroup; - children = ( - F0A987D81F77B404009B603D /* MonitorControl */, - 398F482D5C8816B29F16AAEB /* Pods_MonitorControl.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - F0A987D81F77B404009B603D /* MonitorControl */ = { - isa = PBXGroup; - children = ( - F0A987D91F77B404009B603D /* MainMenu.strings */, - F0A987DB1F77B404009B603D /* Localizable.strings */, - F0A987DD1F77B404009B603D /* Assets.xcassets */, - F0A987DE1F77B404009B603D /* Objects */, - F0A987E01F77B404009B603D /* MainMenu.xib */, - F0A987E21F77B404009B603D /* Utils.swift */, - F0A987E51F77B404009B603D /* AppDelegate.swift */, - F0A987E61F77B404009B603D /* Bridging-Header.h */, - F0A987E71F77B404009B603D /* Info.plist */, - ); - path = MonitorControl; - sourceTree = ""; - }; - F0A987DE1F77B404009B603D /* Objects */ = { - isa = PBXGroup; - children = ( - F0A987DF1F77B404009B603D /* SliderHandler.swift */, - ); - path = Objects; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -439,32 +403,6 @@ name = Localizable.strings; sourceTree = ""; }; - F0A987D91F77B404009B603D /* MainMenu.strings */ = { - isa = PBXVariantGroup; - children = ( - F0A987DA1F77B404009B603D /* en */, - F0A987E31F77B404009B603D /* fr */, - ); - name = MainMenu.strings; - sourceTree = ""; - }; - F0A987DB1F77B404009B603D /* Localizable.strings */ = { - isa = PBXVariantGroup; - children = ( - F0A987DC1F77B404009B603D /* en */, - F0A987E41F77B404009B603D /* fr */, - ); - name = Localizable.strings; - sourceTree = ""; - }; - F0A987E01F77B404009B603D /* MainMenu.xib */ = { - isa = PBXVariantGroup; - children = ( - F0A987E11F77B404009B603D /* Base */, - ); - name = MainMenu.xib; - sourceTree = ""; - }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ diff --git a/MonitorControl/AppDelegate.swift b/MonitorControl/AppDelegate.swift index 275b45c..4e0e13e 100644 --- a/MonitorControl/AppDelegate.swift +++ b/MonitorControl/AppDelegate.swift @@ -16,133 +16,129 @@ var app: AppDelegate! = nil let prefs = UserDefaults.standard @NSApplicationMain -class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate { - +class AppDelegate: NSObject, NSApplicationDelegate { + @IBOutlet weak var statusMenu: NSMenu! @IBOutlet weak var window: NSWindow! - + let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength) - + var monitorItems: [NSMenuItem] = [] var displays: [Display] = [] - - let step = 100/16 - - var mediaKeyTap: MediaKeyTap? - var prefsController: NSWindowController? - - var keysListenedFor: [MediaKey] = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown] - + + let step = 100/16 + + var mediaKeyTap: MediaKeyTap? + var prefsController: NSWindowController? + + var keysListenedFor: [MediaKey] = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown] + func applicationDidFinishLaunching(_ aNotification: Notification) { app = self - - let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue) - if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue { - keysListenedFor.removeSubrange(2...4) - } else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue { - keysListenedFor.removeSubrange(0...1) - } - - mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false) - let storyboard: NSStoryboard = NSStoryboard.init(name: "Main", bundle: Bundle.main) - let views = [ - storyboard.instantiateController(withIdentifier: "MainPrefsVC"), - storyboard.instantiateController(withIdentifier: "KeysPrefsVC"), - storyboard.instantiateController(withIdentifier: "DisplayPrefsVC") - ] - prefsController = MASPreferencesWindowController(viewControllers: views, title: NSLocalizedString("Preferences", comment: "Shown in Preferences window")) - - NotificationCenter.default.addObserver(self, selector: #selector(handleListenForChanged), name: NSNotification.Name.init(Utils.PrefKeys.listenFor.rawValue), object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(handleShowContrastChanged), name: NSNotification.Name.init(Utils.PrefKeys.showContrast.rawValue), object: nil) - - statusItem.image = NSImage.init(named: "status") + + let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue) + if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue { + keysListenedFor.removeSubrange(2...4) + } else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue { + keysListenedFor.removeSubrange(0...1) + } + + mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false) + let storyboard: NSStoryboard = NSStoryboard.init(name: "Main", bundle: Bundle.main) + let views = [ + storyboard.instantiateController(withIdentifier: "MainPrefsVC"), + storyboard.instantiateController(withIdentifier: "KeysPrefsVC"), + storyboard.instantiateController(withIdentifier: "DisplayPrefsVC") + ] + prefsController = MASPreferencesWindowController(viewControllers: views, title: NSLocalizedString("Preferences", comment: "Shown in Preferences window")) + + NotificationCenter.default.addObserver(self, selector: #selector(handleListenForChanged), name: NSNotification.Name.init(Utils.PrefKeys.listenFor.rawValue), object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handleShowContrastChanged), name: NSNotification.Name.init(Utils.PrefKeys.showContrast.rawValue), object: nil) + + statusItem.image = NSImage.init(named: "status") statusItem.menu = statusMenu - - setDefaultPrefs() - + + setDefaultPrefs() + Utils.acquirePrivileges() - + CGDisplayRegisterReconfigurationCallback({_, _, _ in app.updateDisplays()}, nil) updateDisplays() - - mediaKeyTap?.start() + + mediaKeyTap?.start() } - - func applicationWillTerminate(_ aNotification: Notification) { - } - - @IBAction func quitClicked(_ sender: AnyObject) { - NSApplication.shared.terminate(self) - } - - @IBAction func prefsClicked(_ sender: AnyObject) { - if let prefsController = prefsController { - prefsController.showWindow(sender) - NSApp.activate(ignoringOtherApps: true) - prefsController.window?.makeKeyAndOrderFront(sender) - } - } - - /// Set the default prefs of the app - func setDefaultPrefs() { - let prefs = UserDefaults.standard - if !prefs.bool(forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue) { - prefs.set(true, forKey: Utils.PrefKeys.appAlreadyLaunched.rawValue) - - prefs.set(false, forKey: Utils.PrefKeys.startAtLogin.rawValue) - - prefs.set(false, forKey: Utils.PrefKeys.showContrast.rawValue) - prefs.set(false, forKey: Utils.PrefKeys.lowerContrast.rawValue) - } - } - - // MARK: - Menu - - func clearDisplays() { - if statusMenu.items.count > 2 { - var items: [NSMenuItem] = [] - for i in 0.. 2 { + var items: [NSMenuItem] = [] + for i in 0.. Bool in - if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID { - // Is Built In Screen (e.g. MBP/iMac Screen) - if CGDisplayIsBuiltin(id) != 0 { - return false - } - - // Does screen support EDID ? - var edid = EDID() - if !EDIDTest(id, &edid) { - return false - } - - return true - } - return false - } - - if filteredScreens.count == 1 { - self.addScreenToMenu(screen: filteredScreens[0], asSubMenu: false) - } else { - for screen in filteredScreens { - self.addScreenToMenu(screen: screen, asSubMenu: true) - } - } - + clearDisplays() + + var filteredScreens = NSScreen.screens.filter { screen -> Bool in + if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID { + // Is Built In Screen (e.g. MBP/iMac Screen) + if CGDisplayIsBuiltin(id) != 0 { + return false + } + + // Does screen support EDID ? + var edid = EDID() + if !EDIDTest(id, &edid) { + return false + } + + return true + } + return false + } + + if filteredScreens.count == 1 { + self.addScreenToMenu(screen: filteredScreens[0], asSubMenu: false) + } else { + for screen in filteredScreens { + self.addScreenToMenu(screen: screen, asSubMenu: true) + } + } + if filteredScreens.count == 0 { // If no DDC capable display was detected let item = NSMenuItem() @@ -152,103 +148,105 @@ class AppDelegate: NSObject, NSApplicationDelegate, MediaKeyTapDelegate { statusMenu.insertItem(item, at: 0) } } - - /// Add a screen to the menu - /// - /// - Parameters: - /// - screen: The screen to add - /// - asSubMenu: Display in a sub menu or directly in menu - private func addScreenToMenu(screen: NSScreen, asSubMenu: Bool) { - if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID { - - var edid = EDID() - if EDIDTest(id, &edid) { - let name = Utils.getDisplayName(forEdid: edid) - let serial = Utils.getDisplaySerial(forEdid: edid) - - let display = Display.init(id, name: name, serial: serial) - - let monitorSubMenu: NSMenu = asSubMenu ? NSMenu() : statusMenu - let volumeSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, - forDisplay: display, - command: AUDIO_SPEAKER_VOLUME, - title: NSLocalizedString("Volume", comment: "Shown in menu")) - let brightnessSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, - forDisplay: display, - command: BRIGHTNESS, - title: NSLocalizedString("Brightness", comment: "Shown in menu")) - if prefs.bool(forKey: Utils.PrefKeys.showContrast.rawValue) { - let contrastSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, - forDisplay: display, - command: CONTRAST, - title: NSLocalizedString("Contrast", comment: "Shown in menu")) - display.contrastSliderHandler = contrastSliderHandler - } - - display.volumeSliderHandler = volumeSliderHandler - display.brightnessSliderHandler = brightnessSliderHandler - displays.append(display) - - let monitorMenuItem = NSMenuItem() - monitorMenuItem.title = "\(name)" - if asSubMenu { - monitorMenuItem.submenu = monitorSubMenu - } - - monitorItems.append(monitorMenuItem) - statusMenu.insertItem(monitorMenuItem, at: 0) - } - } - } - - // MARK: - Media Key Tap delegate - - func handle(mediaKey: MediaKey, event: KeyEvent?) { - guard let currentDisplay = Utils.getCurrentDisplay(from: displays) else { return } - let allDisplays = prefs.bool(forKey: Utils.PrefKeys.allScreens.rawValue) ? displays : [currentDisplay] - for display in allDisplays { - if (prefs.object(forKey: "\(display.identifier)-state") as? Bool) ?? true { - switch mediaKey { - case .brightnessUp: - let value = display.calcNewValue(for: BRIGHTNESS, withRel: +step) - display.setBrightness(to: value) - case .brightnessDown: - let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: -step) - display.setBrightness(to: value) - case .mute: - display.mute() - case .volumeUp: - let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: +step) - display.setVolume(to: value) - case .volumeDown: - let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: -step) - display.setVolume(to: value) - default: - return - } - } - } - - } - - // MARK: - Prefs notification - - @objc func handleListenForChanged() { - let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue) - keysListenedFor = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown] - if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue { - keysListenedFor.removeSubrange(2...4) - } else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue { - keysListenedFor.removeSubrange(0...1) - } - - mediaKeyTap?.stop() - mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false) - mediaKeyTap?.start() - } - - @objc func handleShowContrastChanged() { - self.updateDisplays() - } - + + /// Add a screen to the menu + /// + /// - Parameters: + /// - screen: The screen to add + /// - asSubMenu: Display in a sub menu or directly in menu + private func addScreenToMenu(screen: NSScreen, asSubMenu: Bool) { + if let id = screen.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as? CGDirectDisplayID { + + var edid = EDID() + if EDIDTest(id, &edid) { + let name = Utils.getDisplayName(forEdid: edid) + let serial = Utils.getDisplaySerial(forEdid: edid) + + let display = Display.init(id, name: name, serial: serial) + + let monitorSubMenu: NSMenu = asSubMenu ? NSMenu() : statusMenu + let volumeSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, + forDisplay: display, + command: AUDIO_SPEAKER_VOLUME, + title: NSLocalizedString("Volume", comment: "Shown in menu")) + let brightnessSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, + forDisplay: display, + command: BRIGHTNESS, + title: NSLocalizedString("Brightness", comment: "Shown in menu")) + if prefs.bool(forKey: Utils.PrefKeys.showContrast.rawValue) { + let contrastSliderHandler = Utils.addSliderMenuItem(toMenu: monitorSubMenu, + forDisplay: display, + command: CONTRAST, + title: NSLocalizedString("Contrast", comment: "Shown in menu")) + display.contrastSliderHandler = contrastSliderHandler + } + + display.volumeSliderHandler = volumeSliderHandler + display.brightnessSliderHandler = brightnessSliderHandler + displays.append(display) + + let monitorMenuItem = NSMenuItem() + monitorMenuItem.title = "\(name)" + if asSubMenu { + monitorMenuItem.submenu = monitorSubMenu + } + + monitorItems.append(monitorMenuItem) + statusMenu.insertItem(monitorMenuItem, at: 0) + } + } + } + +} + +// MARK: - Media Key Tap delegate +extension AppDelegate: MediaKeyTapDelegate { + + func handle(mediaKey: MediaKey, event: KeyEvent?) { + guard let currentDisplay = Utils.getCurrentDisplay(from: displays) else { return } + let allDisplays = prefs.bool(forKey: Utils.PrefKeys.allScreens.rawValue) ? displays : [currentDisplay] + for display in allDisplays { + if (prefs.object(forKey: "\(display.identifier)-state") as? Bool) ?? true { + switch mediaKey { + case .brightnessUp: + let value = display.calcNewValue(for: BRIGHTNESS, withRel: +step) + display.setBrightness(to: value) + case .brightnessDown: + let value = currentDisplay.calcNewValue(for: BRIGHTNESS, withRel: -step) + display.setBrightness(to: value) + case .mute: + display.mute() + case .volumeUp: + let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: +step) + display.setVolume(to: value) + case .volumeDown: + let value = display.calcNewValue(for: AUDIO_SPEAKER_VOLUME, withRel: -step) + display.setVolume(to: value) + default: + return + } + } + } + + } + + // MARK: - Prefs notification + + @objc func handleListenForChanged() { + let listenFor = prefs.integer(forKey: Utils.PrefKeys.listenFor.rawValue) + keysListenedFor = [.brightnessUp, .brightnessDown, .mute, .volumeUp, .volumeDown] + if listenFor == Utils.ListenForKeys.brightnessOnlyKeys.rawValue { + keysListenedFor.removeSubrange(2...4) + } else if listenFor == Utils.ListenForKeys.volumeOnlyKeys.rawValue { + keysListenedFor.removeSubrange(0...1) + } + + mediaKeyTap?.stop() + mediaKeyTap = MediaKeyTap.init(delegate: self, for: keysListenedFor, observeBuiltIn: false) + mediaKeyTap?.start() + } + + @objc func handleShowContrastChanged() { + self.updateDisplays() + } }