11//
22// AppDelegate.swift
3- // MonitorControl.OSX
3+ // MonitorControl
44//
55// Created by Mathew Kurian on 9/26/16.
6- // Copyright © 2016 Mathew Kurian. All rights reserved.
6+ // Last edited by Guillaume Broder on 9/17/2017
7+ // MIT Licensed. 2017.
78//
89
910import Cocoa
@@ -18,47 +19,13 @@ struct Display {
1819var app : AppDelegate ! = nil
1920let prefs = UserDefaults . standard
2021
21- func ddcctl( monitor: CGDirectDisplayID , command: Int32 , value: Int ) {
22- var wrcmd = DDCWriteCommand ( control_id: UInt8 ( command) , new_value: UInt8 ( value) )
23- DDCWrite ( monitor, & wrcmd)
24- print ( value)
25- }
26-
27- class SliderHandler : NSObject {
28- var display : Display
29- var command : Int32 = 0
30-
31- public init ( display: Display , command: Int32 ) {
32- self . display = display
33- self . command = command
34- }
35-
36- func valueChanged( slider: NSSlider ) {
37- let snapInterval = 25
38- let snapThreshold = 3
39-
40- var value = slider. integerValue
41-
42- let closest = ( value + snapInterval / 2 ) / snapInterval * snapInterval
43- if abs ( closest - value) <= snapThreshold {
44- value = closest
45- slider. integerValue = value
46- }
47-
48- ddcctl ( monitor: display. id, command: command, value: value)
49-
50- prefs. setValue ( value, forKey: " \( command) - \( display. serial) " )
51- prefs. synchronize ( )
52- }
53- }
54-
5522@NSApplicationMain
5623class AppDelegate : NSObject , NSApplicationDelegate {
5724
5825 @IBOutlet weak var statusMenu : NSMenu !
5926 @IBOutlet weak var window : NSWindow !
6027
61- let statusItem = NSStatusBar . system ( ) . statusItem ( withLength: NSVariableStatusItemLength )
28+ let statusItem = NSStatusBar . system. statusItem ( withLength: NSStatusItem . variableLength )
6229
6330 var monitorItems : [ NSMenuItem ] = [ ]
6431 var displays : [ Display ] = [ ]
@@ -68,14 +35,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
6835 var defaultBrightnessSlider : NSSlider ! = nil
6936 var defaultVolumeSlider : NSSlider ! = nil
7037
38+ let step = 100 / 16 ;
39+
7140 @IBAction func quitClicked( _ sender: AnyObject ) {
72- NSApplication . shared ( ) . terminate ( self )
41+ NSApplication . shared. terminate ( self )
7342 }
7443
7544 func applicationDidFinishLaunching( _ aNotification: Notification ) {
7645 app = self
7746
78- statusItem. title = " ♨ "
47+ statusItem. image = NSImage . init ( named : NSImage . Name ( rawValue : " status " ) )
7948 statusItem. menu = statusMenu
8049
8150 acquirePrivileges ( )
@@ -84,39 +53,63 @@ class AppDelegate: NSObject, NSApplicationDelegate {
8453 updateDisplays ( )
8554
8655 NSEvent . addGlobalMonitorForEvents (
87- matching: NSEventMask . keyDown, handler: { ( event: NSEvent ) in
56+ matching: NSEvent . EventTypeMask . keyDown, handler: { ( event: NSEvent ) in
8857 if self . defaultDisplay == nil {
8958 return
9059 }
9160
92- let modifiers = NSEventModifierFlags . init ( rawValue: NSEventModifierFlags . command. rawValue |
93- NSEventModifierFlags . control. rawValue |
94- NSEventModifierFlags . option. rawValue |
95- NSEventModifierFlags . shift. rawValue)
96- var flags = event. modifierFlags. intersection ( modifiers)
97-
98- if !flags. contains ( NSEventModifierFlags . command) {
99- return
100- }
101- flags. subtract ( NSEventModifierFlags . command)
102-
103- var rel = 0
104- if event. keyCode == 27 {
105- rel = - 5
106- } else if event. keyCode == 24 {
107- rel = + 5
108- } else {
61+ // Keyboard shortcut only for main screen
62+ let currentDisplayId = NSScreen . main? . deviceDescription [ NSDeviceDescriptionKey . init ( " NSScreenNumber " ) ] as! CGDirectDisplayID
63+ if ( self . defaultDisplay. id != currentDisplayId) {
64+ return
65+ }
66+
67+ // Brightness -> Shift + Control + Alt + Command + (Up/Down)
68+ // Volume -> Shift + Control + Alt + Command + (Left/Right)
69+ // Mute -> Minus
70+
71+ // Capture keys
72+ let modifiers = NSEvent . ModifierFlags. init ( rawValue: NSEvent . ModifierFlags. shift. rawValue | NSEvent . ModifierFlags. command. rawValue | NSEvent . ModifierFlags. control. rawValue | NSEvent . ModifierFlags. option. rawValue)
73+ let flags = event. modifierFlags. intersection ( modifiers)
74+
75+ // Only do something if all modifiers are active
76+ if !flags. contains ( NSEvent . ModifierFlags. shift) || !flags. contains ( NSEvent . ModifierFlags. command) || !flags. contains ( NSEvent . ModifierFlags. control) || !flags. contains ( NSEvent . ModifierFlags. option) {
77+ return
78+ }
79+
80+ var brightnessRel = 0
81+ var volumeRel = 0
82+ var rel = 0
83+
84+ // Down key
85+ if event. keyCode == Utils . key. keyDownArrow. rawValue {
86+ brightnessRel = - self . step
87+ // Up key
88+ } else if event. keyCode == Utils . key. keyUpArrow. rawValue {
89+ brightnessRel = + self . step
90+ // Left key
91+ } else if event. keyCode == Utils . key. keyLeftArrow. rawValue {
92+ volumeRel = - self . step
93+ // Right key
94+ } else if event. keyCode == Utils . key. keyRightArrow. rawValue {
95+ volumeRel = + self . step
96+ // M key
97+ } else if event. keyCode == Utils . key. keyMute. rawValue {
98+ volumeRel = - 100
99+ } else {
109100 return
110101 }
111102
112103 var command = Int32 ( )
113104 var slider : NSSlider ! = nil
114- if flags == NSEventModifierFlags . option {
105+ if brightnessRel == 0 {
115106 command = AUDIO_SPEAKER_VOLUME
116107 slider = self . defaultVolumeSlider
117- } else if flags == NSEventModifierFlags . shift {
108+ rel = volumeRel
109+ } else if volumeRel == 0 {
118110 command = BRIGHTNESS
119111 slider = self . defaultBrightnessSlider
112+ rel = brightnessRel
120113 } else {
121114 return
122115 }
@@ -128,30 +121,27 @@ class AppDelegate: NSObject, NSApplicationDelegate {
128121 prefs. synchronize ( )
129122 slider. intValue = Int32 ( value)
130123
131- ddcctl ( monitor: self . defaultDisplay. id, command: command, value: value)
124+ Utils . ddcctl ( monitor: self . defaultDisplay. id, command: command, value: value)
125+
126+ // OSD
127+ let manager : OSDManager = OSDManager . sharedManager ( ) as! OSDManager
128+ var osdImage : Int = 1 // Brightness Image
129+ if brightnessRel == 0 {
130+ osdImage = 3 // Speaker image
131+ if value == 0 {
132+ osdImage = 4 // Mute speaker
133+ }
134+ }
135+ manager. showImage ( Int64 ( osdImage) , onDisplayID: self . defaultDisplay. id, priority: 0x1f4 , msecUntilFade: 2000 , filledChiclets: UInt32 ( value/ self . step) , totalChiclets: UInt32 ( 100 / self . step) , locked: false )
132136 } )
133137 }
134138
135- func makeLabel( text: String , frame: NSRect ) -> NSTextField {
136- let label = NSTextField ( frame: frame)
137- label. stringValue = text
138- label. isBordered = false
139- label. isBezeled = false
140- label. isEditable = false
141- label. drawsBackground = false
142- return label
143- }
144-
145- func addSliderItem( menu: NSMenu , isDefaultDisplay: Bool , display: Display , command: Int32 , title: String , shortcut: String ) -> NSSlider {
139+ func addSliderItem( menu: NSMenu , isDefaultDisplay: Bool , display: Display , command: Int32 , title: String ) -> NSSlider {
146140 let item = NSMenuItem ( )
147141
148142 let view = NSView ( frame: NSRect ( x: 0 , y: 5 , width: 250 , height: 40 ) )
149143
150- let label = makeLabel ( text: title, frame: NSRect ( x: 20 , y: 19 , width: 130 , height: 20 ) )
151-
152- let labelKeyCode = makeLabel ( text: shortcut, frame: NSRect ( x: 120 , y: 19 , width: 100 , height: 20 ) )
153- labelKeyCode. isHidden = !isDefaultDisplay
154- labelKeyCode. alignment = NSTextAlignment . right
144+ let label = Utils . makeLabel ( text: title, frame: NSRect ( x: 20 , y: 19 , width: 130 , height: 20 ) )
155145
156146 let handler = SliderHandler ( display: display, command: command)
157147 sliderHandlers. append ( handler)
@@ -161,14 +151,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
161151 slider. minValue = 0
162152 slider. maxValue = 100
163153 slider. integerValue = prefs. integer ( forKey: " \( command) - \( display. serial) " )
164- slider. action = #selector( SliderHandler . valueChanged)
154+ slider. action = #selector( SliderHandler . valueChanged)
165155
166156 view. addSubview ( label)
167- view. addSubview ( labelKeyCode)
168157 view. addSubview ( slider)
169158
170159 item. view = view
171-
160+
172161 menu. addItem ( item)
173162 menu. addItem ( NSMenuItem . separator ( ) )
174163
@@ -183,14 +172,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
183172 for m in monitorItems {
184173 statusMenu. removeItem ( m)
185174 }
175+
186176 monitorItems = [ ]
187177 displays = [ ]
188178 sliderHandlers = [ ]
189179
190180 sleep ( 1 )
191181
192- for s in NSScreen . screens ( ) ! {
193- let id = s. deviceDescription [ " NSScreenNumber " ] as! CGDirectDisplayID
182+ for s in NSScreen . screens {
183+ let id = s. deviceDescription [ NSDeviceDescriptionKey . init ( " NSScreenNumber " ) ] as! CGDirectDisplayID
194184 if CGDisplayIsBuiltin ( id) != 0 {
195185 continue
196186 }
@@ -211,17 +201,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
211201 let monitorMenuItem = NSMenuItem ( )
212202 let monitorSubMenu = NSMenu ( )
213203
214- let brightnessSlider = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: BRIGHTNESS, title: " Brightness " , shortcut: " ⇧⌘- / ⇧⌘+ " )
215- let _ = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: CONTRAST, title: " Contrast " , shortcut: " " )
216- let volumeSlider = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: AUDIO_SPEAKER_VOLUME, title: " Volume " , shortcut: " ⌥⌘- / ⌥⌘+ " )
217-
204+ let brightnessSlider = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: BRIGHTNESS, title: NSLocalizedString ( " Brightness " , comment: " Sown in menu " ) )
205+ let _ = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: CONTRAST, title: NSLocalizedString ( " Contrast " , comment: " Shown in menu " ) )
206+ let volumeSlider = addSliderItem ( menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: AUDIO_SPEAKER_VOLUME, title: NSLocalizedString ( " Volume " , comment: " Shown in menu " ) )
218207
219208 let defaultMonitorItem = NSMenuItem ( )
220209 let defaultMonitorView = NSView ( frame: NSRect ( x: 0 , y: 5 , width: 250 , height: 25 ) )
221210
222211 let defaultMonitorSelectButtom = NSButton ( frame: NSRect ( x: 25 , y: 0 , width: 200 , height: 25 ) )
223- defaultMonitorSelectButtom. title = isDefaultDisplay ? " Default " : " Set as default "
224- defaultMonitorSelectButtom. bezelStyle = NSRoundRectBezelStyle
212+ defaultMonitorSelectButtom. title = isDefaultDisplay ? NSLocalizedString ( " Default " , comment : " Shown in menu " ) : NSLocalizedString ( " Set as default " , comment : " Shown in menu " )
213+ defaultMonitorSelectButtom. bezelStyle = NSButton . BezelStyle . rounded
225214 defaultMonitorSelectButtom. isEnabled = !isDefaultDisplay
226215
227216 defaultMonitorView. addSubview ( defaultMonitorSelectButtom)
@@ -246,19 +235,19 @@ class AppDelegate: NSObject, NSApplicationDelegate {
246235 if defaultDisplay == nil {
247236 // If no DDC capable display was detected
248237 let item = NSMenuItem ( )
249- item. title = " No supported display found "
238+ item. title = NSLocalizedString ( " No supported display found " , comment : " Shown in menu " )
250239 item. isEnabled = false
251240 monitorItems. append ( item)
252241 statusMenu. insertItem ( item, at: 0 )
253242 }
254243 }
255-
244+
256245 func acquirePrivileges( ) {
257246 let options : NSDictionary = [ kAXTrustedCheckOptionPrompt. takeRetainedValue ( ) as NSString : true ]
258247 let accessibilityEnabled = AXIsProcessTrustedWithOptions ( options)
259248
260249 if !accessibilityEnabled {
261- print ( " You need to enable the keylogger in the System Prefrences " )
250+ print ( NSLocalizedString ( " You need to enable the keylogger in the System Prefrences for the keyboard shortcuts to work " , comment : " " ) )
262251 }
263252
264253 return
@@ -293,10 +282,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
293282 }
294283
295284 func getDisplayName( _ edid: EDID ) -> String {
296- return getDescriptorString ( edid, 0xFC ) ?? " Display "
285+ return getDescriptorString ( edid, 0xFC ) ?? NSLocalizedString ( " Display " , comment : " " )
297286 }
298287
299288 func getDisplaySerial( _ edid: EDID ) -> String {
300- return getDescriptorString ( edid, 0xFF ) ?? " Unknown "
289+ return getDescriptorString ( edid, 0xFF ) ?? NSLocalizedString ( " Unknown " , comment : " " )
301290 }
302291}
0 commit comments