- More consistent display naming (proper name is shown even if display is shadowed in a mirror).

- Display naming now should match System Report.
- Some cleanup (removed unneccesary OSD.framework folder, stuff moved to Bridging-Header.h, removed search location in Build settings, framework proper linked instead).
This commit is contained in:
waydabber 2021-07-31 20:00:00 +02:00
parent db015509d6
commit f5fcef758e
8 changed files with 80 additions and 57 deletions

View file

@ -14,10 +14,11 @@ You need to have a *single*, *compatible* external display (aside from the inter
- [x] Make DDC read work on Apple Silicon (to set up initial brightness and volume during app start).
- [x] Add proper checks to safeguard things.
- [x] Fix issue with internal display brightness display control on Apple Slicon (relevant services moved to a different private framework)
- [x] Better handling of mirrored displays to prepare for better mulit monitor support
- [ ] Proper external multi monitor support
### About multiple external displays
Unfortunatelly proper external multi monitor support is rather difficult to achieve for several reasons (needs a complicated display matching logic based on various properties). It is doable but needs lots of work and testing to work really well. Also other changes are needed (like fixing how MonitorControl handles mirrored displays). For the M1 class devices this only affects the Mac mini when both HDMI and DP is connected. Even then the HDMI port will not work (which is a hard limitation as of now) so such users probably won't want use MonitorControl anyway. This issue will have to be resolved though for future Apple Silicon devices
Unfortunatelly proper external multi monitor support is rather difficult to achieve for several reasons (needs a complicated display matching logic based on various properties). It is doable but needs lots of work and testing to work really well. ~~Also other changes are needed (like fixing how MonitorControl handles mirrored displays - UPDATE: DONE).~~ For the M1 class devices this only affects the Mac mini when both HDMI and DP is connected. Even then the HDMI port will not work (which is a hard limitation as of now) so such users probably won't want use MonitorControl anyway. This issue will have to be resolved though for future Apple Silicon devices
This does not affect MonitorControl's ability to handle the internal display alongside a single external display connected via USB-C.

View file

@ -21,7 +21,6 @@
6C85EFDD22CBAA8F00227EA1 /* PollingModeCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C85EFDC22CBAA8F00227EA1 /* PollingModeCellView.swift */; };
6C85EFDF22CBB54100227EA1 /* PollingCountCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C85EFDE22CBB54100227EA1 /* PollingCountCellView.swift */; };
6C85EFE122CC00AD00227EA1 /* NSNotification+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C85EFE022CC00AD00227EA1 /* NSNotification+Extension.swift */; };
6CB2B64B263EDA6600F0E0EF /* OSD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0A987D61F77B290009B603D /* OSD.framework */; };
6CBFE27A23DB266000D1BC41 /* Display.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBFE27923DB266000D1BC41 /* Display.swift */; };
6CBFE27C23DB27A200D1BC41 /* InternalDisplay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CBFE27B23DB27A200D1BC41 /* InternalDisplay.swift */; };
6CC260F6256AD8F900613714 /* Preferences+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6CC260F5256AD8F900613714 /* Preferences+Extension.swift */; };
@ -34,6 +33,8 @@
6CDA0FCF26485A8300F52125 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6CDA0FCD26485A8300F52125 /* Main.storyboard */; };
AA3B4A2826AE103C00B74CD2 /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = AA3B4A2726AE103C00B74CD2 /* README.md */; };
AA3B4A2A26AE108E00B74CD2 /* Apple Silicon.md in Resources */ = {isa = PBXBuildFile; fileRef = AA3B4A2926AE108E00B74CD2 /* Apple Silicon.md */; };
AA9AE86F26B5BF3D00B6CA65 /* OSD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9AE86E26B5BF3D00B6CA65 /* OSD.framework */; };
AA9AE87126B5BFB700B6CA65 /* CoreDisplay.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA9AE87026B5BFB700B6CA65 /* CoreDisplay.framework */; };
F01B0699228221B7008E64DB /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F01B0680228221B6008E64DB /* Localizable.strings */; };
F01B069A228221B7008E64DB /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F01B0683228221B6008E64DB /* Utils.swift */; };
F01B069E228221B7008E64DB /* ButtonCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F01B068E228221B6008E64DB /* ButtonCellView.swift */; };
@ -115,6 +116,8 @@
6CDA0FD826485AAE00F52125 /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Main.strings; sourceTree = "<group>"; };
AA3B4A2726AE103C00B74CD2 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
AA3B4A2926AE108E00B74CD2 /* Apple Silicon.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = "Apple Silicon.md"; sourceTree = "<group>"; };
AA9AE86E26B5BF3D00B6CA65 /* OSD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OSD.framework; path = ../../../../../System/Library/PrivateFrameworks/OSD.framework; sourceTree = "<group>"; };
AA9AE87026B5BFB700B6CA65 /* CoreDisplay.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreDisplay.framework; path = ../../../../../System/Library/Frameworks/CoreDisplay.framework; sourceTree = "<group>"; };
B0C4810623357CE500053F91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
B0C4810823357CE500053F91 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/MainMenu.strings; sourceTree = "<group>"; };
F01B0681228221B6008E64DB /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
@ -138,7 +141,6 @@
F06792E9200A73460066C438 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
F06792F0200A73470066C438 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
F06792F1200A73470066C438 /* MonitorControlHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MonitorControlHelper.entitlements; sourceTree = "<group>"; };
F0A987D61F77B290009B603D /* OSD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OSD.framework; sourceTree = "<group>"; };
FE4E0895249D584C003A50BB /* OSDUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OSDUtils.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -147,10 +149,11 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
AA9AE87126B5BFB700B6CA65 /* CoreDisplay.framework in Frameworks */,
6CD35F53264FFFC6001F1344 /* SimplyCoreAudio in Frameworks */,
6CD35F5626500008001F1344 /* MediaKeyTap in Frameworks */,
6CB2B64B263EDA6600F0E0EF /* OSD.framework in Frameworks */,
6CD35F592650002E001F1344 /* DDC in Frameworks */,
AA9AE86F26B5BF3D00B6CA65 /* OSD.framework in Frameworks */,
6CD35F5C2650003F001F1344 /* Preferences in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -168,6 +171,8 @@
28D1DDD1227FB759004CB494 /* Frameworks */ = {
isa = PBXGroup;
children = (
AA9AE86E26B5BF3D00B6CA65 /* OSD.framework */,
AA9AE87026B5BFB700B6CA65 /* CoreDisplay.framework */,
6CC260F9256ADA7400613714 /* Preferences.framework */,
28D1DDE3227FB7D0004CB494 /* AMCoreAudio.framework */,
28D1DE10227FD006004CB494 /* AMCoreAudio.framework.dSYM */,
@ -177,7 +182,6 @@
28D1DE0E227FD005004CB494 /* MASPreferences.framework.dSYM */,
28D1DDE2227FB7D0004CB494 /* MediaKeyTap.framework */,
28D1DE0F227FD006004CB494 /* MediaKeyTap.framework.dSYM */,
F0A987D61F77B290009B603D /* OSD.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -773,6 +777,10 @@
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl/Support/Bridging-Header.h";
SWIFT_VERSION = 5.0;
SYSTEM_FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
);
};
name = Debug;
};
@ -801,6 +809,10 @@
PROVISIONING_PROFILE_SPECIFIER = "";
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl/Support/Bridging-Header.h";
SWIFT_VERSION = 5.0;
SYSTEM_FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks",
);
};
name = Release;
};

View file

@ -86,6 +86,31 @@ class AppDelegate: NSObject, NSApplicationDelegate {
DisplayManager.shared.clearDisplays()
}
func getDisplayName(displayID: CGDirectDisplayID) -> String {
let defaultName: String = NSLocalizedString("Unknown", comment: "Unknown display name") // + String(CGDisplaySerialNumber(displayID))
if let dictionary = ((CoreDisplay_DisplayCreateInfoDictionary(displayID))?.takeRetainedValue() as NSDictionary?), let nameList = dictionary["DisplayProductName"] as? [String: String], let name = nameList[Locale.current.identifier] ?? nameList["en_US"] ?? nameList.first?.value {
return name
}
if let screen = NSScreen.getByDisplayID(displayID: displayID) {
if #available(OSX 10.15, *) {
return screen.localizedName
} else {
return screen.displayName ?? defaultName
}
}
if CGDisplayIsInHWMirrorSet(displayID) != 0 || CGDisplayIsInMirrorSet(displayID) != 0 {
if let mirroredScreen = NSScreen.getByDisplayID(displayID: CGDisplayMirrorsDisplay(displayID)) {
let name = NSLocalizedString("Mirror of", comment: "Shown in case a display mirrors an other display - like 'Mirror of DisplayName")
if #available(OSX 10.15, *) {
return "" + name + " " + String(mirroredScreen.localizedName)
} else {
return "" + name + " " + String(mirroredScreen.displayName ?? defaultName)
}
}
}
return defaultName
}
func updateDisplays() {
self.clearDisplays()
@ -98,23 +123,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
}
for onlineDisplayID in onlineDisplayIDs where onlineDisplayID != 0 {
var name: String = NSLocalizedString("Unknown", comment: "Unknown display name") + String(CGDisplaySerialNumber(onlineDisplayID))
if let screen = NSScreen.getByDisplayID(displayID: onlineDisplayID) {
if #available(OSX 10.15, *) {
name = screen.localizedName
} else {
name = screen.displayName ?? name
}
} else if CGDisplayIsInHWMirrorSet(onlineDisplayID) != 0 || CGDisplayIsInMirrorSet(onlineDisplayID) != 0 {
if let mirroredScreen = NSScreen.getByDisplayID(displayID: CGDisplayMirrorsDisplay(onlineDisplayID)) {
name = NSLocalizedString("Mirror of", comment: "Shown in case a display mirrors an other display - like 'Mirror of DisplayName")
if #available(OSX 10.15, *) {
name = "" + name + " " + String(mirroredScreen.localizedName)
} else {
name = "" + name + " " + String(mirroredScreen.displayName ?? NSLocalizedString("Unknown", comment: "Unknown display name"))
}
}
}
let name = getDisplayName(displayID: onlineDisplayID)
let id = onlineDisplayID
let vendorNumber = CGDisplayVendorNumber(onlineDisplayID)
let modelNumber = CGDisplayVendorNumber(onlineDisplayID)

View file

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1097</string>
<string>1114</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSMinimumSystemVersion</key>

View file

@ -1,10 +1,43 @@
#pragma once
#import <Foundation/Foundation.h>
#import <OSD/OSDManager.h>
#import <IOKit/i2c/IOI2CInterface.h>
#import <CoreGraphics/CoreGraphics.h>
typedef CFTypeRef IOAVService;
extern IOAVService IOAVServiceCreate(CFAllocatorRef allocator);
extern IOReturn IOAVServiceReadI2C(IOAVService service, uint32_t chipAddress, uint32_t offset, void* outputBuffer, uint32_t outputBufferSize);
extern IOReturn IOAVServiceWriteI2C(IOAVService service, uint32_t chipAddress, uint32_t dataAddress, void* inputBuffer, uint32_t inputBufferSize);
extern CFDictionaryRef CoreDisplay_DisplayCreateInfoDictionary(CGDirectDisplayID);
@class NSString;
@protocol OSDUIHelperProtocol
- (void)showFullScreenImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecToAnimate:(unsigned int)arg4;
- (void)fadeClassicImageOnDisplay:(unsigned int)arg1;
- (void)showImageAtPath:(NSString *)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(NSString *)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 filledChiclets:(unsigned int)arg5 totalChiclets:(unsigned int)arg6 locked:(BOOL)arg7;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(NSString *)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4;
@end
@class NSXPCConnection;
@interface OSDManager : NSObject <OSDUIHelperProtocol>
{
id <OSDUIHelperProtocol> _proxyObject;
NSXPCConnection *connection;
}
+ (id)sharedManager;
@property(retain) NSXPCConnection *connection; // @synthesize connection;
- (void)showFullScreenImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecToAnimate:(unsigned int)arg4;
- (void)fadeClassicImageOnDisplay:(unsigned int)arg1;
- (void)showImageAtPath:(id)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(id)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 filledChiclets:(unsigned int)arg5 totalChiclets:(unsigned int)arg6 locked:(BOOL)arg7;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(id)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4;
@property(readonly) id <OSDUIHelperProtocol> remoteObjectProxy; // @dynamic remoteObjectProxy;
@end

View file

@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>1097</string>
<string>1114</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.utilities</string>
<key>LSBackgroundOnly</key>

View file

@ -1,21 +0,0 @@
#import "OSDUIHelperProtocol.h"
@class NSXPCConnection;
@interface OSDManager : NSObject <OSDUIHelperProtocol>
{
id <OSDUIHelperProtocol> _proxyObject;
NSXPCConnection *connection;
}
+ (id)sharedManager;
@property(retain) NSXPCConnection *connection; // @synthesize connection;
- (void)showFullScreenImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecToAnimate:(unsigned int)arg4;
- (void)fadeClassicImageOnDisplay:(unsigned int)arg1;
- (void)showImageAtPath:(id)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(id)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 filledChiclets:(unsigned int)arg5 totalChiclets:(unsigned int)arg6 locked:(BOOL)arg7;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(id)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4;
@property(readonly) id <OSDUIHelperProtocol> remoteObjectProxy; // @dynamic remoteObjectProxy;
@end

View file

@ -1,11 +0,0 @@
@class NSString;
@protocol OSDUIHelperProtocol
- (void)showFullScreenImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecToAnimate:(unsigned int)arg4;
- (void)fadeClassicImageOnDisplay:(unsigned int)arg1;
- (void)showImageAtPath:(NSString *)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(NSString *)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 filledChiclets:(unsigned int)arg5 totalChiclets:(unsigned int)arg6 locked:(BOOL)arg7;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4 withText:(NSString *)arg5;
- (void)showImage:(long long)arg1 onDisplayID:(unsigned int)arg2 priority:(unsigned int)arg3 msecUntilFade:(unsigned int)arg4;
@end