mirror of
https://github.com/MonitorControl/MonitorControl.git
synced 2026-05-15 06:05:52 -06:00
🎉 1.0
- Code rework - Native OSD - Change default shortcuts for problems with apps - Codesign app Signed-off-by: Guillaume Broder <iamnotheoneyouseek@gmail.com>
This commit is contained in:
parent
38137e84e9
commit
036a29d4bc
33 changed files with 689 additions and 158 deletions
BIN
.github/menulet.png
vendored
Normal file
BIN
.github/menulet.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
.github/osd.png
vendored
Normal file
BIN
.github/osd.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 KiB |
21
License.txt
Normal file
21
License.txt
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright © 2017
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<Workspace
|
|
||||||
version = "1.0">
|
|
||||||
<FileRef
|
|
||||||
location = "self:MonitorControl.OSX.xcodeproj">
|
|
||||||
</FileRef>
|
|
||||||
</Workspace>
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>SchemeUserState</key>
|
|
||||||
<dict>
|
|
||||||
<key>MonitorControl.OSX.xcscheme</key>
|
|
||||||
<dict>
|
|
||||||
<key>orderHint</key>
|
|
||||||
<integer>0</integer>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
<key>SuppressBuildableAutocreation</key>
|
|
||||||
<dict>
|
|
||||||
<key>56754EAA1D9A4016007BCDC5</key>
|
|
||||||
<dict>
|
|
||||||
<key>primary</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#include "../ddcctl/DDC.h"
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */; };
|
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */; };
|
||||||
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB01D9A4016007BCDC5 /* Assets.xcassets */; };
|
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB01D9A4016007BCDC5 /* Assets.xcassets */; };
|
||||||
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB21D9A4016007BCDC5 /* MainMenu.xib */; };
|
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 56754EB21D9A4016007BCDC5 /* MainMenu.xib */; };
|
||||||
|
F091C9B31F6EA6110096FD65 /* SliderHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F091C9B21F6EA6110096FD65 /* SliderHandler.swift */; };
|
||||||
|
F091C9B81F6EA79B0096FD65 /* Utils.swift in Sources */ = {isa = PBXBuildFile; fileRef = F091C9B71F6EA79B0096FD65 /* Utils.swift */; };
|
||||||
|
F0A987E81F77B40E009B603D /* OSD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0A987D61F77B290009B603D /* OSD.framework */; };
|
||||||
|
F0EB972F1F6ED7C800686D2A /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = F091C9C11F6EB8660096FD65 /* Localizable.strings */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
|
@ -21,12 +25,30 @@
|
||||||
55359E361E2737EC002671BC /* ddcctl.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ddcctl.sh; sourceTree = "<group>"; };
|
55359E361E2737EC002671BC /* ddcctl.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = ddcctl.sh; sourceTree = "<group>"; };
|
||||||
55359E371E2737EC002671BC /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
55359E371E2737EC002671BC /* Makefile */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.make; path = Makefile; sourceTree = "<group>"; };
|
||||||
55359E381E2737EC002671BC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
55359E381E2737EC002671BC /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
|
||||||
55359E3E1E27380B002671BC /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
|
56754EAB1D9A4016007BCDC5 /* MonitorControl.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonitorControl.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
56754EAB1D9A4016007BCDC5 /* MonitorControl.OSX.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MonitorControl.OSX.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
|
||||||
56754EB01D9A4016007BCDC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
56754EB01D9A4016007BCDC5 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
56754EB31D9A4016007BCDC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
56754EB31D9A4016007BCDC5 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
56754EB51D9A4016007BCDC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
56754EB51D9A4016007BCDC5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
|
F091C9B21F6EA6110096FD65 /* SliderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandler.swift; sourceTree = "<group>"; };
|
||||||
|
F091C9B71F6EA79B0096FD65 /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
|
||||||
|
F091C9B91F6EB43B0096FD65 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = fr; path = fr.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||||
|
F091C9C21F6EB8660096FD65 /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
F091C9C31F6EB8720096FD65 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
F091C9C41F6EBA5A0096FD65 /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
F0A987D51F77A823009B603D /* en */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; lineEnding = 0; name = en; path = en.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||||
|
F0A987D61F77B290009B603D /* OSD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OSD.framework; sourceTree = "<group>"; };
|
||||||
|
F0A987DA1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||||
|
F0A987DC1F77B404009B603D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
F0A987DD1F77B404009B603D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
|
F0A987DF1F77B404009B603D /* SliderHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SliderHandler.swift; sourceTree = "<group>"; };
|
||||||
|
F0A987E11F77B404009B603D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
|
||||||
|
F0A987E21F77B404009B603D /* Utils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Utils.swift; sourceTree = "<group>"; };
|
||||||
|
F0A987E31F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/MainMenu.strings; sourceTree = "<group>"; };
|
||||||
|
F0A987E41F77B404009B603D /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = "<group>"; };
|
||||||
|
F0A987E51F77B404009B603D /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
|
F0A987E61F77B404009B603D /* Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
|
F0A987E71F77B404009B603D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
|
@ -34,6 +56,7 @@
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F0A987E81F77B40E009B603D /* OSD.framework in Frameworks */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -56,38 +79,83 @@
|
||||||
56754EA21D9A4016007BCDC5 = {
|
56754EA21D9A4016007BCDC5 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
56754EAD1D9A4016007BCDC5 /* MonitorControl.OSX */,
|
56754EAD1D9A4016007BCDC5 /* MonitorControl */,
|
||||||
|
F0A987D61F77B290009B603D /* OSD.framework */,
|
||||||
55359E321E2737EC002671BC /* ddcctl */,
|
55359E321E2737EC002671BC /* ddcctl */,
|
||||||
56754EAC1D9A4016007BCDC5 /* Products */,
|
56754EAC1D9A4016007BCDC5 /* Products */,
|
||||||
|
F0A987D71F77B404009B603D /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
56754EAC1D9A4016007BCDC5 /* Products */ = {
|
56754EAC1D9A4016007BCDC5 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
56754EAB1D9A4016007BCDC5 /* MonitorControl.OSX.app */,
|
56754EAB1D9A4016007BCDC5 /* MonitorControl.app */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
56754EAD1D9A4016007BCDC5 /* MonitorControl.OSX */ = {
|
56754EAD1D9A4016007BCDC5 /* MonitorControl */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */,
|
56754EAE1D9A4016007BCDC5 /* AppDelegate.swift */,
|
||||||
|
F091C9B71F6EA79B0096FD65 /* Utils.swift */,
|
||||||
|
F091C9B41F6EA6180096FD65 /* Objects */,
|
||||||
|
F091C9C41F6EBA5A0096FD65 /* Bridging-Header.h */,
|
||||||
56754EB01D9A4016007BCDC5 /* Assets.xcassets */,
|
56754EB01D9A4016007BCDC5 /* Assets.xcassets */,
|
||||||
56754EB21D9A4016007BCDC5 /* MainMenu.xib */,
|
56754EB21D9A4016007BCDC5 /* MainMenu.xib */,
|
||||||
|
F091C9C11F6EB8660096FD65 /* Localizable.strings */,
|
||||||
56754EB51D9A4016007BCDC5 /* Info.plist */,
|
56754EB51D9A4016007BCDC5 /* Info.plist */,
|
||||||
55359E3E1E27380B002671BC /* Bridging-Header.h */,
|
|
||||||
);
|
);
|
||||||
path = MonitorControl.OSX;
|
path = MonitorControl;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F091C9B41F6EA6180096FD65 /* Objects */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F091C9B21F6EA6110096FD65 /* SliderHandler.swift */,
|
||||||
|
);
|
||||||
|
path = Objects;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F0A987D71F77B404009B603D /* Frameworks */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F0A987D81F77B404009B603D /* MonitorControl */,
|
||||||
|
);
|
||||||
|
name = Frameworks;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
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 = "<group>";
|
||||||
|
};
|
||||||
|
F0A987DE1F77B404009B603D /* Objects */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
F0A987DF1F77B404009B603D /* SliderHandler.swift */,
|
||||||
|
);
|
||||||
|
path = Objects;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
56754EAA1D9A4016007BCDC5 /* MonitorControl.OSX */ = {
|
56754EAA1D9A4016007BCDC5 /* MonitorControl */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 56754EB81D9A4016007BCDC5 /* Build configuration list for PBXNativeTarget "MonitorControl.OSX" */;
|
buildConfigurationList = 56754EB81D9A4016007BCDC5 /* Build configuration list for PBXNativeTarget "MonitorControl" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
56754EA71D9A4016007BCDC5 /* Sources */,
|
56754EA71D9A4016007BCDC5 /* Sources */,
|
||||||
56754EA81D9A4016007BCDC5 /* Frameworks */,
|
56754EA81D9A4016007BCDC5 /* Frameworks */,
|
||||||
|
|
@ -97,9 +165,9 @@
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = MonitorControl.OSX;
|
name = MonitorControl;
|
||||||
productName = MonitorControl.OSX;
|
productName = MonitorControl.OSX;
|
||||||
productReference = 56754EAB1D9A4016007BCDC5 /* MonitorControl.OSX.app */;
|
productReference = 56754EAB1D9A4016007BCDC5 /* MonitorControl.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
@ -109,29 +177,31 @@
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 0800;
|
LastSwiftUpdateCheck = 0800;
|
||||||
LastUpgradeCheck = 0820;
|
LastUpgradeCheck = 0900;
|
||||||
ORGANIZATIONNAME = "Mathew Kurian";
|
ORGANIZATIONNAME = "Mathew Kurian";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
56754EAA1D9A4016007BCDC5 = {
|
56754EAA1D9A4016007BCDC5 = {
|
||||||
CreatedOnToolsVersion = 8.0;
|
CreatedOnToolsVersion = 8.0;
|
||||||
|
LastSwiftMigration = 0900;
|
||||||
ProvisioningStyle = Automatic;
|
ProvisioningStyle = Automatic;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 56754EA61D9A4016007BCDC5 /* Build configuration list for PBXProject "MonitorControl.OSX" */;
|
buildConfigurationList = 56754EA61D9A4016007BCDC5 /* Build configuration list for PBXProject "MonitorControl" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 3.2";
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
|
fr,
|
||||||
);
|
);
|
||||||
mainGroup = 56754EA21D9A4016007BCDC5;
|
mainGroup = 56754EA21D9A4016007BCDC5;
|
||||||
productRefGroup = 56754EAC1D9A4016007BCDC5 /* Products */;
|
productRefGroup = 56754EAC1D9A4016007BCDC5 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
56754EAA1D9A4016007BCDC5 /* MonitorControl.OSX */,
|
56754EAA1D9A4016007BCDC5 /* MonitorControl */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
@ -142,6 +212,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */,
|
56754EB11D9A4016007BCDC5 /* Assets.xcassets in Resources */,
|
||||||
|
F0EB972F1F6ED7C800686D2A /* Localizable.strings in Resources */,
|
||||||
55359E3B1E2737EC002671BC /* ddcctl.sh in Resources */,
|
55359E3B1E2737EC002671BC /* ddcctl.sh in Resources */,
|
||||||
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */,
|
56754EB41D9A4016007BCDC5 /* MainMenu.xib in Resources */,
|
||||||
);
|
);
|
||||||
|
|
@ -154,8 +225,10 @@
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
F091C9B31F6EA6110096FD65 /* SliderHandler.swift in Sources */,
|
||||||
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */,
|
56754EAF1D9A4016007BCDC5 /* AppDelegate.swift in Sources */,
|
||||||
55359E391E2737EC002671BC /* DDC.c in Sources */,
|
55359E391E2737EC002671BC /* DDC.c in Sources */,
|
||||||
|
F091C9B81F6EA79B0096FD65 /* Utils.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
@ -166,6 +239,43 @@
|
||||||
isa = PBXVariantGroup;
|
isa = PBXVariantGroup;
|
||||||
children = (
|
children = (
|
||||||
56754EB31D9A4016007BCDC5 /* Base */,
|
56754EB31D9A4016007BCDC5 /* Base */,
|
||||||
|
F091C9B91F6EB43B0096FD65 /* fr */,
|
||||||
|
F0A987D51F77A823009B603D /* en */,
|
||||||
|
);
|
||||||
|
name = MainMenu.xib;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F091C9C11F6EB8660096FD65 /* Localizable.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
F091C9C21F6EB8660096FD65 /* en */,
|
||||||
|
F091C9C31F6EB8720096FD65 /* fr */,
|
||||||
|
);
|
||||||
|
name = Localizable.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F0A987D91F77B404009B603D /* MainMenu.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
F0A987DA1F77B404009B603D /* en */,
|
||||||
|
F0A987E31F77B404009B603D /* fr */,
|
||||||
|
);
|
||||||
|
name = MainMenu.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F0A987DB1F77B404009B603D /* Localizable.strings */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
F0A987DC1F77B404009B603D /* en */,
|
||||||
|
F0A987E41F77B404009B603D /* fr */,
|
||||||
|
);
|
||||||
|
name = Localizable.strings;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
F0A987E01F77B404009B603D /* MainMenu.xib */ = {
|
||||||
|
isa = PBXVariantGroup;
|
||||||
|
children = (
|
||||||
|
F0A987E11F77B404009B603D /* Base */,
|
||||||
);
|
);
|
||||||
name = MainMenu.xib;
|
name = MainMenu.xib;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
|
@ -177,12 +287,15 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
|
@ -190,7 +303,11 @@
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
|
@ -200,6 +317,7 @@
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
|
|
@ -227,12 +345,15 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
|
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
|
@ -240,7 +361,11 @@
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
CLANG_WARN_SUSPICIOUS_MOVES = YES;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
|
|
@ -250,6 +375,7 @@
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
|
|
@ -269,13 +395,18 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
INFOPLIST_FILE = MonitorControl.OSX/Info.plist;
|
DEVELOPMENT_TEAM = "";
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
|
||||||
|
INFOPLIST_FILE = "$(SRCROOT)/MonitorControl/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "bluejamesbond.MonitorControl-OSX";
|
PRODUCT_BUNDLE_IDENTIFIER = me.guillaumeb.MonitorControl;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl.OSX/Bridging-Header.h";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl/Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
|
|
@ -283,20 +414,25 @@
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
INFOPLIST_FILE = MonitorControl.OSX/Info.plist;
|
DEVELOPMENT_TEAM = "";
|
||||||
|
FRAMEWORK_SEARCH_PATHS = "$(PROJECT_DIR)/**";
|
||||||
|
INFOPLIST_FILE = "$(SRCROOT)/MonitorControl/Info.plist";
|
||||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = "bluejamesbond.MonitorControl-OSX";
|
PRODUCT_BUNDLE_IDENTIFIER = me.guillaumeb.MonitorControl;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl.OSX/Bridging-Header.h";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SWIFT_VERSION = 3.0;
|
SWIFT_OBJC_BRIDGING_HEADER = "MonitorControl/Bridging-Header.h";
|
||||||
|
SWIFT_VERSION = 4.0;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
56754EA61D9A4016007BCDC5 /* Build configuration list for PBXProject "MonitorControl.OSX" */ = {
|
56754EA61D9A4016007BCDC5 /* Build configuration list for PBXProject "MonitorControl" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
56754EB61D9A4016007BCDC5 /* Debug */,
|
56754EB61D9A4016007BCDC5 /* Debug */,
|
||||||
|
|
@ -305,7 +441,7 @@
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
56754EB81D9A4016007BCDC5 /* Build configuration list for PBXNativeTarget "MonitorControl.OSX" */ = {
|
56754EB81D9A4016007BCDC5 /* Build configuration list for PBXNativeTarget "MonitorControl" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
56754EB91D9A4016007BCDC5 /* Debug */,
|
56754EB91D9A4016007BCDC5 /* Debug */,
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
//
|
//
|
||||||
// AppDelegate.swift
|
// AppDelegate.swift
|
||||||
// MonitorControl.OSX
|
// MonitorControl
|
||||||
//
|
//
|
||||||
// Created by Mathew Kurian on 9/26/16.
|
// Created by Mathew Kurian on 9/26/16.
|
||||||
// Copyright © 2016 Mathew Kurian. All rights reserved.
|
// Last edited by Guillaume Broder on 9/17/2017
|
||||||
|
// MIT Licensed. 2017.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Cocoa
|
import Cocoa
|
||||||
|
|
@ -18,47 +19,13 @@ struct Display {
|
||||||
var app: AppDelegate! = nil
|
var app: AppDelegate! = nil
|
||||||
let prefs = UserDefaults.standard
|
let prefs = UserDefaults.standard
|
||||||
|
|
||||||
func ddcctl(monitor: CGDirectDisplayID, command: Int32, value: Int) {
|
|
||||||
var wrcmd = DDCWriteCommand(control_id: UInt8(command), new_value: UInt8(value))
|
|
||||||
DDCWrite(monitor, &wrcmd)
|
|
||||||
print(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
class SliderHandler : NSObject {
|
|
||||||
var display : Display
|
|
||||||
var command : Int32 = 0
|
|
||||||
|
|
||||||
public init(display: Display, command: Int32) {
|
|
||||||
self.display = display
|
|
||||||
self.command = command
|
|
||||||
}
|
|
||||||
|
|
||||||
func valueChanged(slider: NSSlider) {
|
|
||||||
let snapInterval = 25
|
|
||||||
let snapThreshold = 3
|
|
||||||
|
|
||||||
var value = slider.integerValue
|
|
||||||
|
|
||||||
let closest = (value + snapInterval / 2) / snapInterval * snapInterval
|
|
||||||
if abs(closest - value) <= snapThreshold {
|
|
||||||
value = closest
|
|
||||||
slider.integerValue = value
|
|
||||||
}
|
|
||||||
|
|
||||||
ddcctl(monitor: display.id, command: command, value: value)
|
|
||||||
|
|
||||||
prefs.setValue(value, forKey: "\(command)-\(display.serial)")
|
|
||||||
prefs.synchronize()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@NSApplicationMain
|
@NSApplicationMain
|
||||||
class AppDelegate: NSObject, NSApplicationDelegate {
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
|
|
||||||
@IBOutlet weak var statusMenu: NSMenu!
|
@IBOutlet weak var statusMenu: NSMenu!
|
||||||
@IBOutlet weak var window: NSWindow!
|
@IBOutlet weak var window: NSWindow!
|
||||||
|
|
||||||
let statusItem = NSStatusBar.system().statusItem(withLength: NSVariableStatusItemLength)
|
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||||
|
|
||||||
var monitorItems: [NSMenuItem] = []
|
var monitorItems: [NSMenuItem] = []
|
||||||
var displays: [Display] = []
|
var displays: [Display] = []
|
||||||
|
|
@ -68,14 +35,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
var defaultBrightnessSlider: NSSlider! = nil
|
var defaultBrightnessSlider: NSSlider! = nil
|
||||||
var defaultVolumeSlider: NSSlider! = nil
|
var defaultVolumeSlider: NSSlider! = nil
|
||||||
|
|
||||||
|
let step = 100/16;
|
||||||
|
|
||||||
@IBAction func quitClicked(_ sender: AnyObject) {
|
@IBAction func quitClicked(_ sender: AnyObject) {
|
||||||
NSApplication.shared().terminate(self)
|
NSApplication.shared.terminate(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
||||||
app = self
|
app = self
|
||||||
|
|
||||||
statusItem.title = "♨"
|
statusItem.image = NSImage.init(named: NSImage.Name(rawValue: "status"))
|
||||||
statusItem.menu = statusMenu
|
statusItem.menu = statusMenu
|
||||||
|
|
||||||
acquirePrivileges()
|
acquirePrivileges()
|
||||||
|
|
@ -84,39 +53,63 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
updateDisplays()
|
updateDisplays()
|
||||||
|
|
||||||
NSEvent.addGlobalMonitorForEvents(
|
NSEvent.addGlobalMonitorForEvents(
|
||||||
matching: NSEventMask.keyDown, handler: {(event: NSEvent) in
|
matching: NSEvent.EventTypeMask.keyDown, handler: {(event: NSEvent) in
|
||||||
if self.defaultDisplay == nil {
|
if self.defaultDisplay == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let modifiers = NSEventModifierFlags.init(rawValue: NSEventModifierFlags.command.rawValue |
|
// Keyboard shortcut only for main screen
|
||||||
NSEventModifierFlags.control.rawValue |
|
let currentDisplayId = NSScreen.main?.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as! CGDirectDisplayID
|
||||||
NSEventModifierFlags.option.rawValue |
|
if (self.defaultDisplay.id != currentDisplayId) {
|
||||||
NSEventModifierFlags.shift.rawValue)
|
return
|
||||||
var flags = event.modifierFlags.intersection(modifiers)
|
}
|
||||||
|
|
||||||
if !flags.contains(NSEventModifierFlags.command) {
|
// Brightness -> Shift + Control + Alt + Command + (Up/Down)
|
||||||
return
|
// Volume -> Shift + Control + Alt + Command + (Left/Right)
|
||||||
}
|
// Mute -> Minus
|
||||||
flags.subtract(NSEventModifierFlags.command)
|
|
||||||
|
|
||||||
var rel = 0
|
// Capture keys
|
||||||
if event.keyCode == 27 {
|
let modifiers = NSEvent.ModifierFlags.init(rawValue: NSEvent.ModifierFlags.shift.rawValue | NSEvent.ModifierFlags.command.rawValue | NSEvent.ModifierFlags.control.rawValue | NSEvent.ModifierFlags.option.rawValue)
|
||||||
rel = -5
|
let flags = event.modifierFlags.intersection(modifiers)
|
||||||
} else if event.keyCode == 24 {
|
|
||||||
rel = +5
|
// Only do something if all modifiers are active
|
||||||
} else {
|
if !flags.contains(NSEvent.ModifierFlags.shift) || !flags.contains(NSEvent.ModifierFlags.command) || !flags.contains(NSEvent.ModifierFlags.control) || !flags.contains(NSEvent.ModifierFlags.option) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var brightnessRel = 0
|
||||||
|
var volumeRel = 0
|
||||||
|
var rel = 0
|
||||||
|
|
||||||
|
// Down key
|
||||||
|
if event.keyCode == Utils.key.keyDownArrow.rawValue {
|
||||||
|
brightnessRel = -self.step
|
||||||
|
// Up key
|
||||||
|
} else if event.keyCode == Utils.key.keyUpArrow.rawValue {
|
||||||
|
brightnessRel = +self.step
|
||||||
|
// Left key
|
||||||
|
} else if event.keyCode == Utils.key.keyLeftArrow.rawValue {
|
||||||
|
volumeRel = -self.step
|
||||||
|
// Right key
|
||||||
|
} else if event.keyCode == Utils.key.keyRightArrow.rawValue {
|
||||||
|
volumeRel = +self.step
|
||||||
|
// M key
|
||||||
|
} else if event.keyCode == Utils.key.keyMute.rawValue {
|
||||||
|
volumeRel = -100
|
||||||
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var command = Int32()
|
var command = Int32()
|
||||||
var slider: NSSlider! = nil
|
var slider: NSSlider! = nil
|
||||||
if flags == NSEventModifierFlags.option {
|
if brightnessRel == 0 {
|
||||||
command = AUDIO_SPEAKER_VOLUME
|
command = AUDIO_SPEAKER_VOLUME
|
||||||
slider = self.defaultVolumeSlider
|
slider = self.defaultVolumeSlider
|
||||||
} else if flags == NSEventModifierFlags.shift {
|
rel = volumeRel
|
||||||
|
} else if volumeRel == 0 {
|
||||||
command = BRIGHTNESS
|
command = BRIGHTNESS
|
||||||
slider = self.defaultBrightnessSlider
|
slider = self.defaultBrightnessSlider
|
||||||
|
rel = brightnessRel
|
||||||
} else {
|
} else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -128,30 +121,27 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
prefs.synchronize()
|
prefs.synchronize()
|
||||||
slider.intValue = Int32(value)
|
slider.intValue = Int32(value)
|
||||||
|
|
||||||
ddcctl(monitor: self.defaultDisplay.id, command: command, value: value)
|
Utils.ddcctl(monitor: self.defaultDisplay.id, command: command, value: value)
|
||||||
|
|
||||||
|
// OSD
|
||||||
|
let manager : OSDManager = OSDManager.sharedManager() as! OSDManager
|
||||||
|
var osdImage : Int = 1 // Brightness Image
|
||||||
|
if brightnessRel == 0 {
|
||||||
|
osdImage = 3 // Speaker image
|
||||||
|
if value == 0 {
|
||||||
|
osdImage = 4 // Mute speaker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
manager.showImage(Int64(osdImage), onDisplayID: self.defaultDisplay.id, priority: 0x1f4, msecUntilFade: 2000, filledChiclets: UInt32(value/self.step), totalChiclets: UInt32(100/self.step), locked: false)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeLabel(text: String, frame: NSRect) -> NSTextField {
|
func addSliderItem(menu: NSMenu, isDefaultDisplay: Bool, display: Display, command: Int32, title: String) -> NSSlider {
|
||||||
let label = NSTextField(frame: frame)
|
|
||||||
label.stringValue = text
|
|
||||||
label.isBordered = false
|
|
||||||
label.isBezeled = false
|
|
||||||
label.isEditable = false
|
|
||||||
label.drawsBackground = false
|
|
||||||
return label
|
|
||||||
}
|
|
||||||
|
|
||||||
func addSliderItem(menu: NSMenu, isDefaultDisplay: Bool, display: Display, command: Int32, title: String, shortcut: String) -> NSSlider {
|
|
||||||
let item = NSMenuItem()
|
let item = NSMenuItem()
|
||||||
|
|
||||||
let view = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 40))
|
let view = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 40))
|
||||||
|
|
||||||
let label = makeLabel(text: title, frame: NSRect(x: 20, y: 19, width: 130, height: 20))
|
let label = Utils.makeLabel(text: title, frame: NSRect(x: 20, y: 19, width: 130, height: 20))
|
||||||
|
|
||||||
let labelKeyCode = makeLabel(text: shortcut, frame: NSRect(x: 120, y: 19, width: 100, height: 20))
|
|
||||||
labelKeyCode.isHidden = !isDefaultDisplay
|
|
||||||
labelKeyCode.alignment = NSTextAlignment.right
|
|
||||||
|
|
||||||
let handler = SliderHandler(display: display, command: command)
|
let handler = SliderHandler(display: display, command: command)
|
||||||
sliderHandlers.append(handler)
|
sliderHandlers.append(handler)
|
||||||
|
|
@ -161,14 +151,13 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
slider.minValue = 0
|
slider.minValue = 0
|
||||||
slider.maxValue = 100
|
slider.maxValue = 100
|
||||||
slider.integerValue = prefs.integer(forKey: "\(command)-\(display.serial)")
|
slider.integerValue = prefs.integer(forKey: "\(command)-\(display.serial)")
|
||||||
slider.action = #selector(SliderHandler.valueChanged)
|
slider.action = #selector(SliderHandler.valueChanged)
|
||||||
|
|
||||||
view.addSubview(label)
|
view.addSubview(label)
|
||||||
view.addSubview(labelKeyCode)
|
|
||||||
view.addSubview(slider)
|
view.addSubview(slider)
|
||||||
|
|
||||||
item.view = view
|
item.view = view
|
||||||
|
|
||||||
menu.addItem(item)
|
menu.addItem(item)
|
||||||
menu.addItem(NSMenuItem.separator())
|
menu.addItem(NSMenuItem.separator())
|
||||||
|
|
||||||
|
|
@ -183,14 +172,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
for m in monitorItems {
|
for m in monitorItems {
|
||||||
statusMenu.removeItem(m)
|
statusMenu.removeItem(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
monitorItems = []
|
monitorItems = []
|
||||||
displays = []
|
displays = []
|
||||||
sliderHandlers = []
|
sliderHandlers = []
|
||||||
|
|
||||||
sleep(1)
|
sleep(1)
|
||||||
|
|
||||||
for s in NSScreen.screens()! {
|
for s in NSScreen.screens {
|
||||||
let id = s.deviceDescription["NSScreenNumber"] as! CGDirectDisplayID
|
let id = s.deviceDescription[NSDeviceDescriptionKey.init("NSScreenNumber")] as! CGDirectDisplayID
|
||||||
if CGDisplayIsBuiltin(id) != 0 {
|
if CGDisplayIsBuiltin(id) != 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
@ -211,17 +201,16 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
let monitorMenuItem = NSMenuItem()
|
let monitorMenuItem = NSMenuItem()
|
||||||
let monitorSubMenu = NSMenu()
|
let monitorSubMenu = NSMenu()
|
||||||
|
|
||||||
let brightnessSlider = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: BRIGHTNESS, title: "Brightness", shortcut: "⇧⌘- / ⇧⌘+")
|
let brightnessSlider = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: BRIGHTNESS, title: NSLocalizedString("Brightness", comment: "Sown in menu"))
|
||||||
let _ = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: CONTRAST, title: "Contrast", shortcut: "")
|
let _ = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: CONTRAST, title: NSLocalizedString("Contrast", comment: "Shown in menu"))
|
||||||
let volumeSlider = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: AUDIO_SPEAKER_VOLUME, title: "Volume", shortcut: "⌥⌘- / ⌥⌘+")
|
let volumeSlider = addSliderItem(menu: monitorSubMenu, isDefaultDisplay: isDefaultDisplay, display: d, command: AUDIO_SPEAKER_VOLUME, title: NSLocalizedString("Volume", comment: "Shown in menu"))
|
||||||
|
|
||||||
|
|
||||||
let defaultMonitorItem = NSMenuItem()
|
let defaultMonitorItem = NSMenuItem()
|
||||||
let defaultMonitorView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 25))
|
let defaultMonitorView = NSView(frame: NSRect(x: 0, y: 5, width: 250, height: 25))
|
||||||
|
|
||||||
let defaultMonitorSelectButtom = NSButton(frame: NSRect(x: 25, y: 0, width: 200, height: 25))
|
let defaultMonitorSelectButtom = NSButton(frame: NSRect(x: 25, y: 0, width: 200, height: 25))
|
||||||
defaultMonitorSelectButtom.title = isDefaultDisplay ? "Default" : "Set as default"
|
defaultMonitorSelectButtom.title = isDefaultDisplay ? NSLocalizedString("Default", comment: "Shown in menu") : NSLocalizedString("Set as default", comment: "Shown in menu")
|
||||||
defaultMonitorSelectButtom.bezelStyle = NSRoundRectBezelStyle
|
defaultMonitorSelectButtom.bezelStyle = NSButton.BezelStyle.rounded
|
||||||
defaultMonitorSelectButtom.isEnabled = !isDefaultDisplay
|
defaultMonitorSelectButtom.isEnabled = !isDefaultDisplay
|
||||||
|
|
||||||
defaultMonitorView.addSubview(defaultMonitorSelectButtom)
|
defaultMonitorView.addSubview(defaultMonitorSelectButtom)
|
||||||
|
|
@ -246,19 +235,19 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
if defaultDisplay == nil {
|
if defaultDisplay == nil {
|
||||||
// If no DDC capable display was detected
|
// If no DDC capable display was detected
|
||||||
let item = NSMenuItem()
|
let item = NSMenuItem()
|
||||||
item.title = "No supported display found"
|
item.title = NSLocalizedString("No supported display found", comment: "Shown in menu")
|
||||||
item.isEnabled = false
|
item.isEnabled = false
|
||||||
monitorItems.append(item)
|
monitorItems.append(item)
|
||||||
statusMenu.insertItem(item, at: 0)
|
statusMenu.insertItem(item, at: 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func acquirePrivileges() {
|
func acquirePrivileges() {
|
||||||
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true]
|
let options: NSDictionary = [kAXTrustedCheckOptionPrompt.takeRetainedValue() as NSString: true]
|
||||||
let accessibilityEnabled = AXIsProcessTrustedWithOptions(options)
|
let accessibilityEnabled = AXIsProcessTrustedWithOptions(options)
|
||||||
|
|
||||||
if !accessibilityEnabled {
|
if !accessibilityEnabled {
|
||||||
print("You need to enable the keylogger in the System Prefrences")
|
print(NSLocalizedString("You need to enable the keylogger in the System Prefrences for the keyboard shortcuts to work", comment: ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
@ -293,10 +282,10 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDisplayName(_ edid: EDID) -> String {
|
func getDisplayName(_ edid: EDID) -> String {
|
||||||
return getDescriptorString(edid, 0xFC) ?? "Display"
|
return getDescriptorString(edid, 0xFC) ?? NSLocalizedString("Display", comment: "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDisplaySerial(_ edid: EDID) -> String {
|
func getDisplaySerial(_ edid: EDID) -> String {
|
||||||
return getDescriptorString(edid, 0xFF) ?? "Unknown"
|
return getDescriptorString(edid, 0xFF) ?? NSLocalizedString("Unknown", comment: "")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
6
MonitorControl/Assets.xcassets/Contents.json
Normal file
6
MonitorControl/Assets.xcassets/Contents.json
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
25
MonitorControl/Assets.xcassets/status.imageset/Contents.json
vendored
Normal file
25
MonitorControl/Assets.xcassets/status.imageset/Contents.json
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "status.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "status@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
},
|
||||||
|
"properties" : {
|
||||||
|
"template-rendering-intent" : "template"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
MonitorControl/Assets.xcassets/status.imageset/status.png
vendored
Normal file
BIN
MonitorControl/Assets.xcassets/status.imageset/status.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
BIN
MonitorControl/Assets.xcassets/status.imageset/status@2x.png
vendored
Normal file
BIN
MonitorControl/Assets.xcassets/status.imageset/status@2x.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13196" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="macosx"/>
|
<deployment identifier="macosx"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13196"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
</customObject>
|
</customObject>
|
||||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="LG_Monitor_Control_Menulet" customModuleProvider="target">
|
<customObject id="Voe-Tx-rLC" customClass="AppDelegate" customModule="MonitorControl" customModuleProvider="target">
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="quitClicked" destination="JTa-2I-AsI" id="pCf-S9-cfs"/>
|
<outlet property="quitClicked" destination="JTa-2I-AsI" id="pCf-S9-cfs"/>
|
||||||
<outlet property="statusMenu" destination="lCi-vw-mwp" id="iBf-iw-RcA"/>
|
<outlet property="statusMenu" destination="lCi-vw-mwp" id="iBf-iw-RcA"/>
|
||||||
16
MonitorControl/Bridging-Header.h
Normal file
16
MonitorControl/Bridging-Header.h
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
//
|
||||||
|
// Bridging-Header.h
|
||||||
|
// MonitorControl
|
||||||
|
//
|
||||||
|
// Created by Guillaume BRODER on 17/09/2017.
|
||||||
|
// MIT Licensed. 2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Bridging_Header_h
|
||||||
|
#define Bridging_Header_h
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
#include "../ddcctl/DDC.h"
|
||||||
|
#import <OSD/OSDManager.h>
|
||||||
|
|
||||||
|
#endif /* Bridging_Header_h */
|
||||||
|
|
@ -20,15 +20,17 @@
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1</string>
|
||||||
|
<key>LSApplicationCategoryType</key>
|
||||||
|
<string>public.app-category.utilities</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
|
||||||
|
<key>LSUIElement</key>
|
||||||
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
<string>Copyright © 2016 Mathew Kurian. All rights reserved.</string>
|
<string>MIT Licensed. 2017.</string>
|
||||||
<key>NSMainNibFile</key>
|
<key>NSMainNibFile</key>
|
||||||
<string>MainMenu</string>
|
<string>MainMenu</string>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string>NSApplication</string>
|
<string>NSApplication</string>
|
||||||
<key>LSUIElement</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
37
MonitorControl/Objects/SliderHandler.swift
Normal file
37
MonitorControl/Objects/SliderHandler.swift
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// SliderHandler.swift
|
||||||
|
// MonitorControl
|
||||||
|
//
|
||||||
|
// Created by Guillaume BRODER on 9/17/2017.
|
||||||
|
// MIT Licensed. 2017.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class SliderHandler: NSObject {
|
||||||
|
var display : Display
|
||||||
|
var command : Int32 = 0
|
||||||
|
|
||||||
|
public init(display: Display, command: Int32) {
|
||||||
|
self.display = display
|
||||||
|
self.command = command
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc func valueChanged(slider: NSSlider) {
|
||||||
|
let snapInterval = 25
|
||||||
|
let snapThreshold = 3
|
||||||
|
|
||||||
|
var value = slider.integerValue
|
||||||
|
|
||||||
|
let closest = (value + snapInterval / 2) / snapInterval * snapInterval
|
||||||
|
if abs(closest - value) <= snapThreshold {
|
||||||
|
value = closest
|
||||||
|
slider.integerValue = value
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils.ddcctl(monitor: display.id, command: command, value: value)
|
||||||
|
|
||||||
|
prefs.setValue(value, forKey: "\(command)-\(display.serial)")
|
||||||
|
prefs.synchronize()
|
||||||
|
}
|
||||||
|
}
|
||||||
55
MonitorControl/Utils.swift
Normal file
55
MonitorControl/Utils.swift
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// Utils.swift
|
||||||
|
// MonitorControl
|
||||||
|
//
|
||||||
|
// Created by Guillaume BRODER on 9/17/2017.
|
||||||
|
// MIT Licensed.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Cocoa
|
||||||
|
|
||||||
|
class Utils: NSObject {
|
||||||
|
|
||||||
|
/// Send command to ddcctl
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - monitor: The id of the Monitor to send the command to
|
||||||
|
/// - command: The command to send
|
||||||
|
/// - value: the value of the command
|
||||||
|
static func ddcctl(monitor: CGDirectDisplayID, command: Int32, value: Int) {
|
||||||
|
var wrcmd = DDCWriteCommand(control_id: UInt8(command), new_value: UInt8(value))
|
||||||
|
DDCWrite(monitor, &wrcmd)
|
||||||
|
print(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a label
|
||||||
|
///
|
||||||
|
/// - Parameters:
|
||||||
|
/// - text: The text of the label
|
||||||
|
/// - frame: The frame of the label
|
||||||
|
/// - Returns: An `NSTextField` label
|
||||||
|
static func makeLabel(text: String, frame: NSRect) -> NSTextField {
|
||||||
|
let label = NSTextField(frame: frame)
|
||||||
|
label.stringValue = text
|
||||||
|
label.isBordered = false
|
||||||
|
label.isBezeled = false
|
||||||
|
label.isEditable = false
|
||||||
|
label.drawsBackground = false
|
||||||
|
return label
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Enum for hardware independent keyCode
|
||||||
|
///
|
||||||
|
/// - keyLeftArrow: keyCode for the left arrow
|
||||||
|
/// - keyRightArrow: keyCode for the right arrow
|
||||||
|
/// - keyDownArrow: keyCode for the down arrow
|
||||||
|
/// - keyUpArrow: keyCode for the up arrow
|
||||||
|
enum key : Int {
|
||||||
|
case keyLeftArrow = 123
|
||||||
|
case keyRightArrow = 124
|
||||||
|
case keyDownArrow = 125
|
||||||
|
case keyUpArrow = 126
|
||||||
|
case keyMute = 24
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
MonitorControl/en.lproj/Localizable.strings
Normal file
BIN
MonitorControl/en.lproj/Localizable.strings
Normal file
Binary file not shown.
3
MonitorControl/en.lproj/MainMenu.strings
Normal file
3
MonitorControl/en.lproj/MainMenu.strings
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "JTa-2I-AsI"; */
|
||||||
|
"JTa-2I-AsI.title" = "Quit";
|
||||||
BIN
MonitorControl/fr.lproj/Localizable.strings
Normal file
BIN
MonitorControl/fr.lproj/Localizable.strings
Normal file
Binary file not shown.
3
MonitorControl/fr.lproj/MainMenu.strings
Normal file
3
MonitorControl/fr.lproj/MainMenu.strings
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
/* Class = "NSMenuItem"; title = "Quit"; ObjectID = "JTa-2I-AsI"; */
|
||||||
|
"JTa-2I-AsI.title" = "Quitter";
|
||||||
21
OSD.framework/Headers/OSDManager.h
Normal file
21
OSD.framework/Headers/OSDManager.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
#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
|
||||||
11
OSD.framework/Headers/OSDUIHelperProtocol.h
Normal file
11
OSD.framework/Headers/OSDUIHelperProtocol.h
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
@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
|
||||||
|
|
||||||
1
OSD.framework/OSD
Symbolic link
1
OSD.framework/OSD
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
Versions/Current/OSD
|
||||||
1
OSD.framework/Resources
Symbolic link
1
OSD.framework/Resources
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
Versions/Current/Resources
|
||||||
BIN
OSD.framework/Versions/A/OSD
Executable file
BIN
OSD.framework/Versions/A/OSD
Executable file
Binary file not shown.
46
OSD.framework/Versions/A/Resources/Info.plist
Normal file
46
OSD.framework/Versions/A/Resources/Info.plist
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>BuildMachineOSBuild</key>
|
||||||
|
<string>16B2657</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>OSD</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.apple.OSD</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>OSD</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
|
<array>
|
||||||
|
<string>MacOSX</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>DTCompiler</key>
|
||||||
|
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||||
|
<key>DTPlatformBuild</key>
|
||||||
|
<string>9L173x</string>
|
||||||
|
<key>DTPlatformVersion</key>
|
||||||
|
<string>GM</string>
|
||||||
|
<key>DTSDKBuild</key>
|
||||||
|
<string>17A317</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx10.13internal</string>
|
||||||
|
<key>DTXcode</key>
|
||||||
|
<string>0900</string>
|
||||||
|
<key>DTXcodeBuild</key>
|
||||||
|
<string>9L173x</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright © 2015 Apple Inc. All rights reserved.</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
18
OSD.framework/Versions/A/Resources/version.plist
Normal file
18
OSD.framework/Versions/A/Resources/version.plist
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>BuildAliasOf</key>
|
||||||
|
<string>OSDFramework</string>
|
||||||
|
<key>BuildVersion</key>
|
||||||
|
<string>487</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>ProjectName</key>
|
||||||
|
<string>OSDFramework</string>
|
||||||
|
<key>SourceVersion</key>
|
||||||
|
<string>27000000000000</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
139
OSD.framework/Versions/A/_CodeSignature/CodeResources
Normal file
139
OSD.framework/Versions/A/_CodeSignature/CodeResources
Normal file
|
|
@ -0,0 +1,139 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>files</key>
|
||||||
|
<dict>
|
||||||
|
<key>Resources/Info.plist</key>
|
||||||
|
<data>
|
||||||
|
bTy7OXKIr2tY7ToPw28ekz1xUXU=
|
||||||
|
</data>
|
||||||
|
<key>Resources/version.plist</key>
|
||||||
|
<data>
|
||||||
|
d0I/dBV8v16urCBanZt9RaZvG1E=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>files2</key>
|
||||||
|
<dict>
|
||||||
|
<key>Resources/Info.plist</key>
|
||||||
|
<dict>
|
||||||
|
<key>hash2</key>
|
||||||
|
<data>
|
||||||
|
uEmRq0D23jBsIWK+0+UH3bCcn16eQdAwKWglrQbTfQc=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
<key>Resources/version.plist</key>
|
||||||
|
<dict>
|
||||||
|
<key>hash2</key>
|
||||||
|
<data>
|
||||||
|
f4xR2tymy1G7xEyxX1+yXJmSgOrrndsypu67avrQ8Ss=
|
||||||
|
</data>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>rules</key>
|
||||||
|
<dict>
|
||||||
|
<key>^Resources/</key>
|
||||||
|
<true/>
|
||||||
|
<key>^Resources/.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version.plist$</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>rules2</key>
|
||||||
|
<dict>
|
||||||
|
<key>.*\.dSYM($|/)</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>11</real>
|
||||||
|
</dict>
|
||||||
|
<key>^(.*/)?\.DS_Store$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>2000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
|
||||||
|
<dict>
|
||||||
|
<key>nested</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>10</real>
|
||||||
|
</dict>
|
||||||
|
<key>^.*</key>
|
||||||
|
<true/>
|
||||||
|
<key>^Info\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^PkgInfo$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/.*\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>optional</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1000</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/.*\.lproj/locversion.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>omit</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1100</real>
|
||||||
|
</dict>
|
||||||
|
<key>^Resources/Base\.lproj/</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>1010</real>
|
||||||
|
</dict>
|
||||||
|
<key>^[^/]+$</key>
|
||||||
|
<dict>
|
||||||
|
<key>nested</key>
|
||||||
|
<true/>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>10</real>
|
||||||
|
</dict>
|
||||||
|
<key>^embedded\.provisionprofile$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
<key>^version\.plist$</key>
|
||||||
|
<dict>
|
||||||
|
<key>weight</key>
|
||||||
|
<real>20</real>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
1
OSD.framework/Versions/Current
Symbolic link
1
OSD.framework/Versions/Current
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
A
|
||||||
1
OSD.framework/XPCServices
Symbolic link
1
OSD.framework/XPCServices
Symbolic link
|
|
@ -0,0 +1 @@
|
||||||
|
Versions/Current/XPCServices
|
||||||
40
README.md
40
README.md
|
|
@ -1,10 +1,40 @@
|
||||||
# MonitorControl.OSX
|
# MonitorControl
|
||||||
A menu let to control your monitor (brightness, contrast, volume)
|
|
||||||
|
|
||||||

|
Control your external monitor brightness, contrast or volume directly from a menulet or with keyboard shortcuts :
|
||||||
|
|
||||||
Compatible with most Dell monitors and LG including 27UD68
|
- Brightness: `⇧` + `⌃` + `⌥` + `⌘` + `↑/↓` (Shift + Control + Alt + Command + Up/Down arrows)
|
||||||
|
- Volume: `⇧` + `⌃` + `⌥` + `⌘` + `←/→` (Shift + Control + Alt + Command + Left/Right arrows)
|
||||||
|
- Mute: `⇧` + `⌃` + `⌥` + `⌘` + `-` (Shift + Control + Alt + Command + Minus)
|
||||||
|
|
||||||
|
(Ps. The keyboard shortcut only work for the default screen)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Download
|
||||||
|
|
||||||
|
Go to [Release](./) and download the latest `.dmg`
|
||||||
|
|
||||||
|
## Brightness/Volume default key
|
||||||
|
You can use [Karabiner Elements](https://github.com/tekezo/Karabiner-Elements/) to use the default mac key (`F1`, `F2` for brightness and `F10`, `F11`, `F12` for volume) with this set of custom rules : [Karabiner rules for MonitorControl](karabiner://karabiner/assets/complex_modifications/import?url=https%3A%2F%2Fraw.githubusercontent.com%2Fthe0neyouseek%2FMonitorControl%2Fmaster%2F.github%2Frules.json)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Powered by [@kfix/ddcctl](https://github.com/kfix/ddcctl)
|
Bonus: Using keyboard shortcuts display the native osd :
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## TODO
|
||||||
|
|
||||||
|
- [ ] Hande multiple screen for keyboard shortcut (Possibly the choice to have all screen brightness/volume increase/decrease at the same time or separatly)
|
||||||
|
- [ ] Skip Karabiner use for keyboard shortcut
|
||||||
|
- [ ] Option to start app at login
|
||||||
|
- [ ] Add [SwiftLint](https://github.com/realm/SwiftLint)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
- macOS Sierra (`10.12`) and up.
|
||||||
|
- Works with monitors comptaible with [@kfix/ddcctl](https://github.com/kfix/ddcctl)
|
||||||
|
|
||||||
|
## Thanks
|
||||||
|
- @bluejamesbond (Original developer)
|
||||||
|
- @Tyilo (Fork)
|
||||||
|
- @Bensge - (Used some code from his project [NativeDisplayBrightness](https://github.com/Bensge/NativeDisplayBrightness))
|
||||||
Loading…
Add table
Add a link
Reference in a new issue