diff --git a/MTMR.xcodeproj/project.pbxproj b/MTMR.xcodeproj/project.pbxproj index b78985f..8a0f4f0 100644 --- a/MTMR.xcodeproj/project.pbxproj +++ b/MTMR.xcodeproj/project.pbxproj @@ -7,12 +7,16 @@ objects = { /* Begin PBXBuildFile section */ + B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D621205E03F5006E6B86 /* TouchBarController.swift */; }; + B059D624205E04F3006E6B86 /* TouchBarItems.swift in Sources */ = {isa = PBXBuildFile; fileRef = B059D623205E04F3006E6B86 /* TouchBarItems.swift */; }; + B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B059D62C205F11E8006E6B86 /* DFRFoundation.framework */; }; B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B252205C7D8000BC04DC /* AppDelegate.swift */; }; B082B255205C7D8000BC04DC /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B254205C7D8000BC04DC /* ViewController.swift */; }; B082B257205C7D8000BC04DC /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B082B256205C7D8000BC04DC /* Assets.xcassets */; }; B082B25A205C7D8000BC04DC /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B082B258205C7D8000BC04DC /* Main.storyboard */; }; B082B266205C7D8000BC04DC /* MTMRTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B265205C7D8000BC04DC /* MTMRTests.swift */; }; B082B271205C7D8000BC04DC /* MTMRUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B082B270205C7D8000BC04DC /* MTMRUITests.swift */; }; + B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */; }; B0C1CFCA205C97D30021C862 /* WindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C1CFC9205C97D30021C862 /* WindowController.swift */; }; /* End PBXBuildFile section */ @@ -34,6 +38,11 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + B059D621205E03F5006E6B86 /* TouchBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarController.swift; sourceTree = ""; }; + B059D623205E04F3006E6B86 /* TouchBarItems.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TouchBarItems.swift; sourceTree = ""; }; + B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TouchBarPrivateApi.h; sourceTree = ""; }; + B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TouchBarPrivateApi-Bridging.h"; sourceTree = ""; }; + B059D62C205F11E8006E6B86 /* DFRFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DFRFoundation.framework; path = ../../../../../System/Library/PrivateFrameworks/DFRFoundation.framework; sourceTree = ""; }; B082B24F205C7D8000BC04DC /* MTMR.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MTMR.app; sourceTree = BUILT_PRODUCTS_DIR; }; B082B252205C7D8000BC04DC /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; B082B254205C7D8000BC04DC /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; @@ -47,6 +56,7 @@ B082B26C205C7D8000BC04DC /* MTMRUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MTMRUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; B082B270205C7D8000BC04DC /* MTMRUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MTMRUITests.swift; sourceTree = ""; }; B082B272205C7D8000BC04DC /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyPress.swift; sourceTree = ""; }; B0C1CFC9205C97D30021C862 /* WindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = WindowController.swift; path = ../WindowController.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -55,6 +65,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + B059D62D205F11E8006E6B86 /* DFRFoundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -75,6 +86,14 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + B059D62B205F11E8006E6B86 /* Frameworks */ = { + isa = PBXGroup; + children = ( + B059D62C205F11E8006E6B86 /* DFRFoundation.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; B082B246205C7D8000BC04DC = { isa = PBXGroup; children = ( @@ -82,6 +101,7 @@ B082B264205C7D8000BC04DC /* MTMRTests */, B082B26F205C7D8000BC04DC /* MTMRUITests */, B082B250205C7D8000BC04DC /* Products */, + B059D62B205F11E8006E6B86 /* Frameworks */, ); sourceTree = ""; }; @@ -98,10 +118,15 @@ B082B251205C7D8000BC04DC /* MTMR */ = { isa = PBXGroup; children = ( + B0C1CFC9205C97D30021C862 /* WindowController.swift */, + B059D629205E13E5006E6B86 /* TouchBarPrivateApi.h */, + B059D62A205F0E7D006E6B86 /* TouchBarPrivateApi-Bridging.h */, B082B252205C7D8000BC04DC /* AppDelegate.swift */, B082B254205C7D8000BC04DC /* ViewController.swift */, - B0C1CFC9205C97D30021C862 /* WindowController.swift */, B082B256205C7D8000BC04DC /* Assets.xcassets */, + B0A7E9A9205D6AA400EEF070 /* KeyPress.swift */, + B059D623205E04F3006E6B86 /* TouchBarItems.swift */, + B059D621205E03F5006E6B86 /* TouchBarController.swift */, B082B258205C7D8000BC04DC /* Main.storyboard */, B082B25B205C7D8000BC04DC /* Info.plist */, B082B25C205C7D8000BC04DC /* MTMR.entitlements */, @@ -260,9 +285,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + B059D622205E03F5006E6B86 /* TouchBarController.swift in Sources */, B082B255205C7D8000BC04DC /* ViewController.swift in Sources */, B0C1CFCA205C97D30021C862 /* WindowController.swift in Sources */, B082B253205C7D8000BC04DC /* AppDelegate.swift in Sources */, + B059D624205E04F3006E6B86 /* TouchBarItems.swift in Sources */, + B0A7E9AA205D6AA400EEF070 /* KeyPress.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -423,10 +451,15 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = D6D8BR2QNB; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); INFOPLIST_FILE = MTMR/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "MTMR/TouchBarPrivateApi-Bridging.h"; SWIFT_VERSION = 4.0; }; name = Debug; @@ -439,10 +472,15 @@ CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; DEVELOPMENT_TEAM = D6D8BR2QNB; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(SYSTEM_LIBRARY_DIR)/PrivateFrameworks", + ); INFOPLIST_FILE = MTMR/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = Toxblh.MTMR; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "MTMR/TouchBarPrivateApi-Bridging.h"; SWIFT_VERSION = 4.0; }; name = Release; diff --git a/MTMR/AppDelegate.swift b/MTMR/AppDelegate.swift index feae374..f6ab644 100644 --- a/MTMR/AppDelegate.swift +++ b/MTMR/AppDelegate.swift @@ -14,6 +14,7 @@ class AppDelegate: NSObject, NSApplicationDelegate { func applicationDidFinishLaunching(_ aNotification: Notification) { + TouchBarController.shared.setupControlStripPresence() // Insert code here to initialize your application } diff --git a/MTMR/Assets.xcassets/Contents.json b/MTMR/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/MTMR/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MTMR/Assets.xcassets/Strip.imageset/Contents.json b/MTMR/Assets.xcassets/Strip.imageset/Contents.json new file mode 100644 index 0000000..384a95f --- /dev/null +++ b/MTMR/Assets.xcassets/Strip.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "mtmrIcon.pdf", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/MTMR/Assets.xcassets/Strip.imageset/mtmrIcon.pdf b/MTMR/Assets.xcassets/Strip.imageset/mtmrIcon.pdf new file mode 100644 index 0000000..b4522d3 Binary files /dev/null and b/MTMR/Assets.xcassets/Strip.imageset/mtmrIcon.pdf differ diff --git a/MTMR/Base.lproj/Main.storyboard b/MTMR/Base.lproj/Main.storyboard index 1274c44..f6bf9b9 100644 --- a/MTMR/Base.lproj/Main.storyboard +++ b/MTMR/Base.lproj/Main.storyboard @@ -1,10 +1,8 @@ - - @@ -695,92 +693,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -793,13 +706,24 @@ - + + + + + + + + + + + + - + diff --git a/MTMR/KeyPress.swift b/MTMR/KeyPress.swift new file mode 100644 index 0000000..b74be39 --- /dev/null +++ b/MTMR/KeyPress.swift @@ -0,0 +1,30 @@ +// +// KeyPress.swift +// MTMR +// +// Created by Anton Palgunov on 17/03/2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Foundation + + +func KeyPress (keyCode: CGKeyCode) { + let keyDown = CGEvent(keyboardEventSource: nil, virtualKey: keyCode, keyDown: true) + let keyUp = CGEvent(keyboardEventSource: nil, virtualKey: keyCode, keyDown: false) + + keyDown?.post(tap: .cghidEventTap) + keyUp?.post(tap: .cghidEventTap) +} + +func ESCKeyPress() { + KeyPress(keyCode: 53) +} + +func BrightnessUpPress() { + KeyPress(keyCode: 107) +} + +func BrightnessDownPress() { + KeyPress(keyCode: 113) +} diff --git a/MTMR/TouchBarController.swift b/MTMR/TouchBarController.swift new file mode 100644 index 0000000..1b33a44 --- /dev/null +++ b/MTMR/TouchBarController.swift @@ -0,0 +1,103 @@ +// +// TouchBar.swift +// MTMR +// +// Created by Anton Palgunov on 18/03/2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Cocoa + +class TouchBarController: NSObject, NSTouchBarDelegate { + + static let shared = TouchBarController() + + let touchBar = NSTouchBar() + + private override init() { + super.init() + touchBar.delegate = self + touchBar.defaultItemIdentifiers = [.escButton, .volumeUp, .volumeDown, .time, .preferences] + self.presentTouchBar() + } + + func setupControlStripPresence() { + DFRSystemModalShowsCloseBoxWhenFrontMost(true) + let item = NSCustomTouchBarItem(identifier: .controlStripItem) + item.view = NSButton(image: #imageLiteral(resourceName: "Strip"), target: self, action: #selector(presentTouchBar)) + NSTouchBarItem.addSystemTrayItem(item) + DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true) + } + + func updateControlStripPresence() { + DFRElementSetControlStripPresenceForIdentifier(.controlStripItem, true) + } + + @objc private func presentTouchBar() { + NSTouchBar.presentSystemModalFunctionBar(touchBar, systemTrayItemIdentifier: .controlStripItem) + } + + private func dismissTouchBar() { + NSTouchBar.minimizeSystemModalFunctionBar(touchBar) + } + + func touchBar(_ touchBar: NSTouchBar, makeItemForIdentifier identifier: NSTouchBarItem.Identifier) -> NSTouchBarItem? { + switch identifier { + case .escButton: + let item = NSCustomTouchBarItem(identifier: identifier) + item.view = NSButton(title: "ESC", target: self, action: #selector(handleEsc)) + return item + case .volumeDown: + let item = NSCustomTouchBarItem(identifier: identifier) + item.view = NSButton(title: "V-", target: self, action: #selector(handleVolumeDown)) + return item + case .volumeUp: + let item = NSCustomTouchBarItem(identifier: identifier) + item.view = NSButton(title: "V+", target: self, action: #selector(handleVolumeUp)) + return item + default: + return nil + } + } + + @objc func handleEsc() { + ESCKeyPress() + } + + @objc func handleVolumeUp() { + self.volume(directon: "up") + } + + @objc func handleVolumeDown() { + self.volume(directon: "down") + } + + func volume(directon: String) { + var myAppleScript = "set volume output volume (output volume of (get volume settings) - 5)" + + if (directon == "up") { + myAppleScript = "set volume output volume (output volume of (get volume settings) + 5)" + } + + var error: NSDictionary? + if let scriptObject = NSAppleScript(source: myAppleScript) { + let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError(&error) + + print(output.stringValue as Any) + + if (error != nil) { + print("error: \(String(describing: error))") + } + } + } + + @objc func brightness(directon: String) { + if (directon == "up") { + BrightnessUpPress() + print("BR - Up") + } else { + BrightnessDownPress() + print("BR - Down") + } + } +} diff --git a/MTMR/TouchBarItems.swift b/MTMR/TouchBarItems.swift new file mode 100644 index 0000000..1c12c87 --- /dev/null +++ b/MTMR/TouchBarItems.swift @@ -0,0 +1,19 @@ +// +// TouchBarItems.swift +// MTMR +// +// Created by Anton Palgunov on 18/03/2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +import Cocoa + +extension NSTouchBarItem.Identifier { + static let escButton = NSTouchBarItem.Identifier("com.toxblh.mtmr.escButton") + static let time = NSTouchBarItem.Identifier("com.toxblh.mtmr.time") + static let volumeUp = NSTouchBarItem.Identifier("com.toxblh.mtmr.volumeUp") + static let volumeDown = NSTouchBarItem.Identifier("com.toxblh.mtmr.volumeDown") + static let preferences = NSTouchBarItem.Identifier("com.toxblh.mtmr.preferences") + + static let controlStripItem = NSTouchBarItem.Identifier("com.toxblh.mtmr.controlStrip") +} diff --git a/MTMR/TouchBarPrivateApi-Bridging.h b/MTMR/TouchBarPrivateApi-Bridging.h new file mode 100644 index 0000000..ce3ddc4 --- /dev/null +++ b/MTMR/TouchBarPrivateApi-Bridging.h @@ -0,0 +1,9 @@ +// +// TouchBarPrivateApi-Bridging.h +// MTMR +// +// Created by Anton Palgunov on 18/03/2018. +// Copyright © 2018 Anton Palgunov. All rights reserved. +// + +#import "TouchBarPrivateApi.h" diff --git a/MTMR/TouchBarPrivateApi.h b/MTMR/TouchBarPrivateApi.h new file mode 100644 index 0000000..dbf6c3e --- /dev/null +++ b/MTMR/TouchBarPrivateApi.h @@ -0,0 +1,27 @@ + +#import + +extern void DFRElementSetControlStripPresenceForIdentifier(NSTouchBarItemIdentifier, BOOL); + +extern void DFRSystemModalShowsCloseBoxWhenFrontMost(BOOL); + +@interface NSTouchBarItem (PrivateMethods) + ++ (void)addSystemTrayItem:(NSTouchBarItem *)item; + ++ (void)removeSystemTrayItem:(NSTouchBarItem *)item; + +@end + +@interface NSTouchBar (PrivateMethods) + +// presentSystemModalFunctionBar:placement:systemTrayItemIdentifier: ++ (void)presentSystemModalFunctionBar:(NSTouchBar *)touchBar placement:(long long)placement systemTrayItemIdentifier:(NSTouchBarItemIdentifier)identifier; + ++ (void)presentSystemModalFunctionBar:(NSTouchBar *)touchBar systemTrayItemIdentifier:(NSTouchBarItemIdentifier)identifier; + ++ (void)dismissSystemModalFunctionBar:(NSTouchBar *)touchBar; + ++ (void)minimizeSystemModalFunctionBar:(NSTouchBar *)touchBar; + +@end diff --git a/README.md b/README.md index 6e8e94b..cca13db 100644 --- a/README.md +++ b/README.md @@ -1 +1,17 @@ +

+ +

+ # My TouchBar. My rules + +My the idea is to create the program like a platform for plugins for customization TouchBar. I very like BTT and a full custom TouchBar. And I want to create it. And it's my the first Swift project for MacOS :) + +### Roadmap +- [x] Create the first prototype with TouchBar in Storyboard +- [x] Put in stripe menu on startup the application +- [ ] Find how to simulate real buttons like brightness, volume, night shift and etc. +- [ ] First the weather plugin +- [ ] Create the same panel like in my [BTT preset](https://github.com/Toxblh/btt-touchbar-preset) +- [ ] Find how to open full-screen TouchBar without the cross and stripe menu +- [ ] Find how to add haptic feedback +- [ ] Refactoring the application on packages (AppleScript, JavaScript? and Swift?) diff --git a/Resources/MTMRicon.sketch b/Resources/MTMRicon.sketch new file mode 100644 index 0000000..9f0f1d4 Binary files /dev/null and b/Resources/MTMRicon.sketch differ diff --git a/Resources/logo.png b/Resources/logo.png new file mode 100644 index 0000000..be0b8d2 Binary files /dev/null and b/Resources/logo.png differ diff --git a/WindowController.swift b/WindowController.swift index dbfcd49..baaf6f1 100644 --- a/WindowController.swift +++ b/WindowController.swift @@ -10,73 +10,8 @@ import Cocoa class WindowController: NSWindowController { - func volume(directon: String) { - var myAppleScript = "set volume output volume (output volume of (get volume settings) - 5)" - - if (directon == "up") { - myAppleScript = "set volume output volume (output volume of (get volume settings) + 5)" - } - - var error: NSDictionary? - if let scriptObject = NSAppleScript(source: myAppleScript) { - if let output: NSAppleEventDescriptor = scriptObject.executeAndReturnError( - &error) { - print(output.stringValue as Any) - } else if (error != nil) { - print("error: \(String(describing: error))") - } - } - } - - func brightness(directon: String) { - let CodeUp: UInt16 = 107 - let CodeDown: UInt16 = 113 - let src = CGEventSource(stateID: .hidSystemState) - - let upd = CGEvent(keyboardEventSource: src, virtualKey: CodeUp, keyDown: true) - let upu = CGEvent(keyboardEventSource: src, virtualKey: CodeUp, keyDown: false) - let downd = CGEvent(keyboardEventSource: src, virtualKey: CodeDown, keyDown: true) - let downu = CGEvent(keyboardEventSource: src, virtualKey: CodeDown, keyDown: false) - - let loc = CGEventTapLocation.cghidEventTap - - if (directon == "up") { - upd?.post(tap: loc) - upu?.post(tap: loc) - print(CodeUp) - } else { - downd?.post(tap: loc) - downu?.post(tap: loc) - print(CodeDown) - } - } - - - @IBAction func brightUp(_ sender: Any) { - NSHapticFeedbackManager.defaultPerformer.perform(.generic, performanceTime: .now) - brightness(directon: "up") - } - - @IBAction func brightDown(_ sender: Any) { - NSHapticFeedbackManager.defaultPerformer.perform(.alignment, performanceTime: .now) - brightness(directon: "down") - } - - - @IBAction func volumeUp(_ sender: Any) { - NSHapticFeedbackManager.defaultPerformer.perform(.levelChange, performanceTime: .now); - self.volume(directon: "up") - } - - @IBAction func volumeDown(_ sender: Any) { - NSHapticFeedbackManager.defaultPerformer.perform(.generic, performanceTime: .now) - self.volume(directon: "down") - } - - @IBOutlet weak var timeLabel: NSTextField! - override func windowDidLoad() { super.windowDidLoad() - + } }