Skip to content

Commit 30da9a8

Browse files
authored
Version 4.0.0 (MonitorControl#629)
### Added/improved functionality - Added proper support for controlling Apple displays. - Added option to show/hide brightness slider. - Added option to show brightness slider for internal display and apple displays (enabled by default). - Replication of built-in and Apple display brightness to corresponding brightness slider. - Added suffix to similarly named displays for better differentiation. - Option to disable slider snapping for finer control + disable slider snapping by default. - Added option to show slider tick marks for better accuracy. - Added option to use window focus instead of mouse to determine which display to control. - Ctrl+Command+Brightness now controls external displays only (Ctrl+Brightness continues to control internal display only) - Added separate tab for menu options. - Added option to restore last saved values upon startup. - Added option for audio device name matching for display volume control selection. - Separated option to change all screens for brightness and volume. - Added option for keyboard fine scale for brightness. - Added option for keyboard fine scale for volume. - Added version check upon startup for mandatory preferences reset upon downgrade or incompatible previous version + notification about this. - Added implementation for Command+F1 macOS shortcut to enable/disable mirroring. - Added safer 'Assume last saved settings are valid' option as default instead of startup DDC read (or restore). - Streamlined preference panes, 'Show advanced settings' now affect all tabs. This leads to a better and safer first timer experience (especially because of the influx of many new features). - Added a Quit button to Preferences if menu is hidden (it was not passible to quit the application until this time in this mode only by re-enabling the menu). - Lowered default first-run volume DDC default from 75% to 15% if read is not possible or disabled to prevent unexpectedly loud sound. - Added slider skew setting on a per control basis to have the ability to manipulate DDC slider balance and OSD scale if display control is not linear. - Added the ability to set min. and max. DDC bounds on a per display, per control basis. - Audio device name override option for a display (manually assign a specific audio device to a display). - Advanced setting to invert DDC control range (some displays have the scale reversed). - Advanced setting to remap DDC control code (some displays have contrast and brightness mixed up). - Ability to mark a DDC control as available or unavailable in advanced settings under Displays. - Ability to automatically hide menu icon if there is no slider present in the menu. - Option to show slider percentage for more precision. - Option to set combined or separate OSD scale when combined hardware+software brightness is used. - Apple like smooth brightness change (both for software, hardware, mixed and DisplayServices). - Added support for DisplayLink, AirPlay, Sidecar, screen sharing etc. using window shades (this is an inferior technique to the existing software implementation - gamma control - but still better than nothing). Disabled for any kind of mirroring setups. _(Only on Big Sur and above)_ - Brightness change synchronisation from Built-In and Apple displays to other displays. This makes Touch Bar, Ambient light sensor, Control Center and System Preferences induced changes affect all displays. Synchronisation uses a sophisticated indirect delta method + the user can intervene and adjust individual screen brightness at any time to easily compensate mismatching native brightness levels. - Preferences pane tab selector has a simpler look on Catalina. - All menu sliders are now scrollable using a magic mouse/trackpad swipes or mouse wheel. - Added option for menu to show only items that are relevant to display which shows the menu currently. - Added option to enable combined sliders (note: this option combined with enabled Apple/built-in display syncing and enabled 'change all' keyboard settings finally provides full synchronised control of all displays). - Combined sliders can now display multiple displays when keyboard and brightness syncing is not enabled. _(Only on Big Sur and above)_ - Redesigned sliders to look like Big Sur/Monterey Control Center's sliders. _(Only on Big Sur and above)_ - Quit and Preferences... are now icons for a much cleaner look. _(Only on Big Sur and above)_ - Added option to change additional menu options style or hide them. _(Only on Big Sur and above)_ - Multiple displays are now in nice Big Sur styled blocks - no more ugly separators. _(Only on Big Sur and above)_ - Added customisable gamma/ddc switchover point for combined brightness in the advanced section of Displays. - Added comma separated list for control code override to enable edge cases like controlling Brightness and Contrast at the same time (use VCP list entry `10, 12` for that) - Contrast can now be controlled from keyboard via <kbd>control</kbd> + <kbd>option</kbd> + <kbd>command</kbd> + brightness up/down. - Custom keyboard shortcuts for brightness, contrast, volume and mute - Added automatic update. ### Other under the hood changes and bug fixes - Standardised internal scale among various displays and DDC ranges for ranged controls. - Uses the new internal scale for combined hardware-software brightness mode. - Migrated scales to internal float representation to prevent loss of fine detail on transformations. - Fixed double sound when muting multiple external displays at the same time. - Fixed lack of initial volume configuration if slider is not shown in menu. - Fixed wrong settings being applied to a display when replaced on Apple Silicon (UserDefaults preferences are now tied to specific display strings instead of CGDirectDisplayID - which is no longer semi-unique on arm64). - A lot of refactoring, streamlining and general optimisations.
1 parent 5947be2 commit 30da9a8

File tree

100 files changed

+12504
-4617
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

100 files changed

+12504
-4617
lines changed

.github/screenshot.png

359 KB
Loading

MonitorControl.xcodeproj/project.pbxproj

Lines changed: 180 additions & 168 deletions
Large diffs are not rendered by default.

MonitorControl/AppDelegate.swift

Lines changed: 0 additions & 487 deletions
This file was deleted.
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
public enum Command: UInt8 {
1+
// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
2+
3+
enum Command: UInt8 {
4+
case none = 0
5+
26
// Display Control
37
case horizontalFrequency = 0xAC
48
case verticalFrequency = 0xAE

MonitorControl/Enums/PrefKey.swift

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
2+
3+
enum PrefKey: String {
4+
// Enable mute DDC for display
5+
case enableMuteUnmute
6+
7+
// Sparkle automatic checks
8+
case SUEnableAutomaticChecks
9+
10+
// Hide OSD for display
11+
case hideOsd
12+
13+
// Longer delay DDC for display
14+
case longerDelay
15+
16+
// DDC polling mode for display
17+
case pollingMode
18+
19+
// DDC polling count for display
20+
case pollingCount
21+
22+
// Command value display
23+
case value
24+
25+
// Min command value display
26+
case minDDCOverride
27+
28+
// Max command value display
29+
case maxDDC
30+
31+
// Max user override command value display
32+
case maxDDCOverride
33+
34+
// Max command value display
35+
case curveDDC
36+
37+
// Is the specific control is set as unavailable for display?
38+
case unavailableDDC
39+
40+
// Invert DDC scale?
41+
case invertDDC
42+
43+
// Override DDC control command code
44+
case remapDDC
45+
46+
// User assigned audio device name for display
47+
case audioDeviceNameOverride
48+
49+
// Display disabled for keyboard control
50+
case isDisabled
51+
52+
// Force software mode for display
53+
case forceSw
54+
55+
// Software brightness for display
56+
case SwBrightness
57+
58+
// Build number
59+
case buildNumber
60+
61+
// Was the app launched once
62+
case appAlreadyLaunched
63+
64+
// Hide menu icon
65+
case menuIcon
66+
67+
// Menu item style
68+
case menuItemStyle
69+
70+
// Keys listened for
71+
case keyboardBrightness
72+
73+
// Keys listened for
74+
case keyboardVolume
75+
76+
// Don't listen to F14/F15
77+
case disableAltBrightnessKeys
78+
79+
// Hide brightness sliders
80+
case hideBrightness
81+
82+
// Show volume sliders
83+
case showContrast
84+
85+
// Show volume sliders
86+
case hideVolume
87+
88+
// Lower via software after brightness
89+
case disableCombinedBrightness
90+
91+
// Lower via software after brightness
92+
case combinedBrightnessSwitchingPoint
93+
94+
// Use separated OSD scale for combined brightness
95+
case separateCombinedScale
96+
97+
// Fallback to software control for other displays with no DDC
98+
case disableSoftwareFallback
99+
100+
// Do not show sliders for Apple displays (including built-in display) in menu
101+
case hideAppleFromMenu
102+
103+
// Disable slider snapping
104+
case enableSliderSnap
105+
106+
// Disable slider snapping
107+
case enableSliderPercent
108+
109+
// Show tick marks for sliders
110+
case showTickMarks
111+
112+
// Friendly name changed
113+
case friendlyName
114+
115+
// Instead of assuming default values, enable read or write upon startup (according to readDDCInsteadOfRestoreValues)
116+
case enableDDCDuringStartup
117+
118+
// Restore last saved values upon startup or wake
119+
case readDDCInsteadOfRestoreValues
120+
121+
// Show advanced options under Displays tab in Preferences
122+
case showAdvancedSettings
123+
124+
// Change Brightness for all screens
125+
case allScreensBrightness
126+
127+
// Use focus instead of mouse position to determine which display to control for brightness
128+
case useFocusInsteadOfMouse
129+
130+
// Change Volume for all screens
131+
case allScreensVolume
132+
133+
// Use audio device name matching to determine display to control for volume
134+
case useAudioDeviceNameMatching
135+
136+
// Use fine OSD scale for brightness
137+
case useFineScaleBrightness
138+
139+
// Use fine OSD scale for volume
140+
case useFineScaleVolume
141+
142+
// Use smoothBrightness
143+
case disableSmoothBrightness
144+
145+
// Synchronize brightness from sync source displays among all other displays
146+
case enableBrightnessSync
147+
148+
// Show only relevant slider for menu (depending on which display shows the menu)
149+
case slidersRelevant
150+
151+
// Combine sliders for all displays
152+
case slidersCombine
153+
}
154+
155+
enum PollingMode: Int {
156+
case none = -2
157+
case minimal = -1
158+
case normal = 0
159+
case heavy = 1
160+
case custom = 2
161+
}
162+
163+
enum MenuIcon: Int {
164+
case show = 0
165+
case sliderOnly = 1
166+
case hide = 2
167+
}
168+
169+
enum MenuItemStyle: Int {
170+
case text = 0
171+
case icon = 1
172+
case hide = 2
173+
}
174+
175+
enum KeyboardBrightness: Int {
176+
case media = 0
177+
case custom = 1
178+
case both = 2
179+
case disabled = 3
180+
}
181+
182+
enum KeyboardVolume: Int {
183+
case media = 0
184+
case custom = 1
185+
case both = 2
186+
case disabled = 3
187+
}

MonitorControl/Extensions/CGDirectDisplayID+Extension.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
2+
13
import Cocoa
24

35
public extension CGDirectDisplayID {

MonitorControl/Extensions/Display+Extension.swift

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
2+
3+
import KeyboardShortcuts
4+
5+
extension KeyboardShortcuts.Name {
6+
static let brightnessUp = Self("brightnessUp")
7+
static let brightnessDown = Self("brightnessDown")
8+
static let contrastUp = Self("contrastUp")
9+
static let contrastDown = Self("contrastDown")
10+
static let volumeUp = Self("volumeUp")
11+
static let volumeDown = Self("volumeDown")
12+
static let mute = Self("mute")
13+
14+
static let none = Self("none")
15+
}

MonitorControl/Extensions/NSNotification+Extension.swift

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,4 @@ import Cocoa
22

33
extension NSNotification.Name {
44
static let accessibilityApi = NSNotification.Name(rawValue: "com.apple.accessibility.api")
5-
static let listenFor = NSNotification.Name(rawValue: Utils.PrefKeys.listenFor.rawValue)
6-
static let friendlyName = NSNotification.Name(rawValue: Utils.PrefKeys.friendlyName.rawValue)
7-
static let preferenceReset = NSNotification.Name(rawValue: Utils.PrefKeys.preferenceReset.rawValue)
8-
static let displayListUpdate = NSNotification.Name(rawValue: Utils.PrefKeys.displayListUpdate.rawValue)
95
}

MonitorControl/Extensions/NSScreen+Extension.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
// Copyright © MonitorControl. @JoniVR, @theOneyouseek, @waydabber and others
2+
13
import Cocoa
24

35
public extension NSScreen {
@@ -6,7 +8,7 @@ public extension NSScreen {
68
}
79

810
var vendorNumber: UInt32? {
9-
switch self.displayID.vendorNumber {
11+
switch CGDisplayVendorNumber(self.displayID) {
1012
case 0xFFFF_FFFF:
1113
return nil
1214
case let vendorNumber:
@@ -15,7 +17,7 @@ public extension NSScreen {
1517
}
1618

1719
var modelNumber: UInt32? {
18-
switch self.displayID.modelNumber {
20+
switch CGDisplayModelNumber(self.displayID) {
1921
case 0xFFFF_FFFF:
2022
return nil
2123
case let modelNumber:
@@ -24,7 +26,7 @@ public extension NSScreen {
2426
}
2527

2628
var serialNumber: UInt32? {
27-
switch self.displayID.serialNumber {
29+
switch CGDisplaySerialNumber(self.displayID) {
2830
case 0x0000_0000:
2931
return nil
3032
case let serialNumber:
@@ -56,12 +58,4 @@ public extension NSScreen {
5658

5759
return nil
5860
}
59-
60-
var isBuiltin: Bool {
61-
return CGDisplayIsBuiltin(self.displayID) != 0
62-
}
63-
64-
static func getByDisplayID(displayID: CGDirectDisplayID) -> NSScreen? {
65-
return NSScreen.screens.first { $0.displayID == displayID }
66-
}
6761
}

0 commit comments

Comments
 (0)