From 5b54612d91129afb92aee01e14984e7e2e401709 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Wed, 6 May 2015 20:41:51 -0700 Subject: [PATCH] Pass authtoken in from user, and add a wrapper for web UI on Mac. --- ext/mac-ui-macgap1-wrapper/LICENSE | 25 + .../MacGap.xcodeproj/project.pbxproj | 492 +++ .../contents.xcworkspacedata | 7 + .../xcshareddata/MacGap.xccheckout | 41 + .../UserInterfaceState.xcuserstate | Bin 0 -> 46675 bytes .../UserInterfaceState.xcuserstate | Bin 0 -> 18268 bytes .../WorkspaceSettings.xcsettings | 10 + .../UserInterfaceState.xcuserstate | Bin 0 -> 27811 bytes .../WorkspaceSettings.xcsettings | 10 + .../xcdebugger/Breakpoints.xcbkptlist | 131 + .../xcschemes/MacGap.xcscheme | 86 + .../xcschemes/xcschememanagement.plist | 22 + .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 + .../api.xcuserdatad/xcschemes/MacGap.xcscheme | 88 + .../xcschemes/xcschememanagement.plist | 22 + .../xcdebugger/Breakpoints.xcbkptlist | 161 + .../xcschemes/MacGap.xcscheme | 84 + .../xcschemes/xcschememanagement.plist | 22 + .../MacGap/AppDelegate.h | 18 + .../MacGap/AppDelegate.m | 110 + .../MacGap/Classes/CallbackDelegate.h | 20 + .../MacGap/Classes/CallbackDelegate.m | 168 + .../MacGap/Classes/Commands/App.h | 21 + .../MacGap/Classes/Commands/App.m | 128 + .../MacGap/Classes/Commands/Command.h | 18 + .../MacGap/Classes/Commands/Command.m | 28 + .../MacGap/Classes/Commands/Dock.h | 11 + .../MacGap/Classes/Commands/Dock.m | 31 + .../MacGap/Classes/Commands/MenuItemProxy.h | 31 + .../MacGap/Classes/Commands/MenuItemProxy.m | 150 + .../MacGap/Classes/Commands/MenuProxy.h | 31 + .../MacGap/Classes/Commands/MenuProxy.m | 233 ++ .../MacGap/Classes/Commands/Notice.h | 26 + .../MacGap/Classes/Commands/Notice.m | 108 + .../MacGap/Classes/Commands/Path.h | 21 + .../MacGap/Classes/Commands/Path.m | 53 + .../MacGap/Classes/Commands/Sound.h | 17 + .../MacGap/Classes/Commands/Sound.m | 97 + .../MacGap/Classes/Commands/UserDefaults.h | 43 + .../MacGap/Classes/Commands/UserDefaults.m | 211 + .../MacGap/Classes/Commands/fonts.h | 9 + .../MacGap/Classes/Commands/fonts.m | 48 + .../MacGap/Classes/Constants.h | 7 + .../MacGap/Classes/ContentView.h | 15 + .../MacGap/Classes/ContentView.m | 68 + .../MacGap/Classes/JSEventHelper.h | 20 + .../MacGap/Classes/JSEventHelper.m | 41 + .../MacGap/Classes/Utils.h | 20 + .../MacGap/Classes/Utils.m | 93 + .../MacGap/Classes/WebViewDelegate.h | 49 + .../MacGap/Classes/WebViewDelegate.m | 206 + .../MacGap/Classes/Window.h | 23 + .../MacGap/Classes/Window.m | 94 + ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.h | 10 + ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.m | 51 + .../MacGap/MacGap-Info.plist | 34 + .../MacGap/MacGap-Prefix.pch | 15 + .../MacGap/WindowController.h | 13 + .../MacGap/WindowController.m | 54 + .../MacGap/en.lproj/Credits.rtf | 13 + .../MacGap/en.lproj/InfoPlist.strings | 2 + .../MacGap/en.lproj/MainMenu.xib | 3404 +++++++++++++++++ .../MacGap/en.lproj/Window.xib | 337 ++ ext/mac-ui-macgap1-wrapper/MacGap/main.m | 14 + ext/mac-ui-macgap1-wrapper/README.md | 36 + ext/mac-ui-macgap1-wrapper/application.icns | Bin 0 -> 88566 bytes ext/mac-ui-macgap1-wrapper/public/index.html | 33 + ui/main.jsx | 49 +- 68 files changed, 7537 insertions(+), 1 deletion(-) create mode 100644 ext/mac-ui-macgap1-wrapper/LICENSE create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.pbxproj create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/WorkspaceSettings.xcsettings create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MacGap.xcscheme create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/MacGap.xcscheme create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/MacGap.xcscheme create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.m create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.h create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.m create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.h create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.m create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.h create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.m create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.h create mode 100755 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Constants.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Info.plist create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Prefix.pch create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/WindowController.h create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/WindowController.m create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Credits.rtf create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/InfoPlist.strings create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/MainMenu.xib create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Window.xib create mode 100644 ext/mac-ui-macgap1-wrapper/MacGap/main.m create mode 100644 ext/mac-ui-macgap1-wrapper/README.md create mode 100644 ext/mac-ui-macgap1-wrapper/application.icns create mode 100644 ext/mac-ui-macgap1-wrapper/public/index.html diff --git a/ext/mac-ui-macgap1-wrapper/LICENSE b/ext/mac-ui-macgap1-wrapper/LICENSE new file mode 100644 index 000000000..c7fd4a4a5 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/LICENSE @@ -0,0 +1,25 @@ +MacGap was ported from phonegap-mac, and is under the same license (MIT) + +The MIT License +***************** + +Copyright (c) <2012> + + 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. + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.pbxproj b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.pbxproj new file mode 100644 index 000000000..ea339cf0a --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.pbxproj @@ -0,0 +1,492 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */ = {isa = PBXBuildFile; fileRef = 1495814E15C15CCC00E1CFE5 /* Notice.m */; }; + 6F169DA718CC332E005EDDF3 /* Command.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA618CC332E005EDDF3 /* Command.m */; }; + 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */; }; + 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */; }; + 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */; }; + 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 6F169DB018CD906F005EDDF3 /* MenuProxy.m */; }; + 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD672B518FE618E00C0DAAD /* UserDefaults.m */; }; + 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */ = {isa = PBXBuildFile; fileRef = 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */; }; + 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 88746BED14CCA435001E160E /* JSEventHelper.m */; }; + 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0645F14BDE10A00E4BCE2 /* Window.m */; }; + 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */ = {isa = PBXBuildFile; fileRef = 88C0646414BDEC5800E4BCE2 /* Window.xib */; }; + 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 88C0646C14BDF6A600E4BCE2 /* WindowController.m */; }; + C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1C2B9901AFB0CF10060D7C2 /* Security.framework */; }; + F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */ = {isa = PBXBuildFile; fileRef = F2B80015179E0FC100B069A8 /* Clipboard.m */; }; + FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA32509C14BA813600BF0781 /* WebKit.framework */; }; + FA3250C314BA85E700BF0781 /* ContentView.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BC14BA85E700BF0781 /* ContentView.m */; }; + FA3250C514BA85E700BF0781 /* Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250BE14BA85E700BF0781 /* Utils.m */; }; + FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C014BA85E700BF0781 /* WebViewDelegate.m */; }; + FA3250D314BA860800BF0781 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250C914BA860800BF0781 /* App.m */; }; + FA3250D514BA860800BF0781 /* Dock.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CB14BA860800BF0781 /* Dock.m */; }; + FA3250D914BA860800BF0781 /* Path.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250CF14BA860800BF0781 /* Path.m */; }; + FA3250DB14BA860800BF0781 /* Sound.m in Sources */ = {isa = PBXBuildFile; fileRef = FA3250D114BA860800BF0781 /* Sound.m */; }; + FA3250E514BA883A00BF0781 /* public in Resources */ = {isa = PBXBuildFile; fileRef = FA3250E414BA883A00BF0781 /* public */; }; + FA3250E714BA8BCE00BF0781 /* application.icns in Resources */ = {isa = PBXBuildFile; fileRef = FA3250E614BA8BCE00BF0781 /* application.icns */; }; + FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FA3F7741168F70780027B324 /* Cocoa.framework */; }; + FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FAE451C714BA79C600190544 /* InfoPlist.strings */; }; + FAE451CB14BA79C600190544 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451CA14BA79C600190544 /* main.m */; }; + FAE451CF14BA79C600190544 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = FAE451CD14BA79C600190544 /* Credits.rtf */; }; + FAE451D214BA79C600190544 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FAE451D114BA79C600190544 /* AppDelegate.m */; }; + FAE451D514BA79C600190544 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = FAE451D314BA79C600190544 /* MainMenu.xib */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + FA3250DD14BA876F00BF0781 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1495814D15C15CCC00E1CFE5 /* Notice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Notice.h; path = Classes/Commands/Notice.h; sourceTree = ""; }; + 1495814E15C15CCC00E1CFE5 /* Notice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Notice.m; path = Classes/Commands/Notice.m; sourceTree = ""; }; + 6F169DA518CC332E005EDDF3 /* Command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Command.h; path = Classes/Commands/Command.h; sourceTree = ""; }; + 6F169DA618CC332E005EDDF3 /* Command.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Command.m; path = Classes/Commands/Command.m; sourceTree = ""; }; + 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CallbackDelegate.h; path = Classes/CallbackDelegate.h; sourceTree = ""; }; + 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CallbackDelegate.m; path = Classes/CallbackDelegate.m; sourceTree = ""; }; + 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; + 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuItemProxy.h; path = Classes/Commands/MenuItemProxy.h; sourceTree = ""; }; + 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuItemProxy.m; path = Classes/Commands/MenuItemProxy.m; sourceTree = ""; }; + 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MenuProxy.h; path = Classes/Commands/MenuProxy.h; sourceTree = ""; }; + 6F169DB018CD906F005EDDF3 /* MenuProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MenuProxy.m; path = Classes/Commands/MenuProxy.m; sourceTree = ""; }; + 6FD672B418FE618E00C0DAAD /* UserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UserDefaults.h; path = Classes/Commands/UserDefaults.h; sourceTree = ""; }; + 6FD672B518FE618E00C0DAAD /* UserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UserDefaults.m; path = Classes/Commands/UserDefaults.m; sourceTree = ""; }; + 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = fonts.h; path = Classes/Commands/fonts.h; sourceTree = ""; }; + 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = fonts.m; path = Classes/Commands/fonts.m; sourceTree = ""; }; + 88746BEC14CCA435001E160E /* JSEventHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = JSEventHelper.h; path = Classes/JSEventHelper.h; sourceTree = ""; }; + 88746BED14CCA435001E160E /* JSEventHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = JSEventHelper.m; path = Classes/JSEventHelper.m; sourceTree = ""; }; + 88C0645E14BDE10A00E4BCE2 /* Window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Window.h; path = Classes/Window.h; sourceTree = ""; }; + 88C0645F14BDE10A00E4BCE2 /* Window.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Window.m; path = Classes/Window.m; sourceTree = ""; }; + 88C0646514BDEC5800E4BCE2 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/Window.xib; sourceTree = ""; }; + 88C0646B14BDF6A600E4BCE2 /* WindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WindowController.h; sourceTree = ""; }; + 88C0646C14BDF6A600E4BCE2 /* WindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WindowController.m; sourceTree = ""; }; + C1C2B9901AFB0CF10060D7C2 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + F2B80014179E0FC100B069A8 /* Clipboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Clipboard.h; sourceTree = ""; }; + F2B80015179E0FC100B069A8 /* Clipboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Clipboard.m; sourceTree = ""; }; + FA32509C14BA813600BF0781 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; + FA3250BA14BA85E700BF0781 /* Constants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Constants.h; path = Classes/Constants.h; sourceTree = ""; }; + FA3250BB14BA85E700BF0781 /* ContentView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ContentView.h; path = Classes/ContentView.h; sourceTree = ""; }; + FA3250BC14BA85E700BF0781 /* ContentView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = ContentView.m; path = Classes/ContentView.m; sourceTree = ""; }; + FA3250BD14BA85E700BF0781 /* Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Utils.h; path = Classes/Utils.h; sourceTree = ""; }; + FA3250BE14BA85E700BF0781 /* Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Utils.m; path = Classes/Utils.m; sourceTree = ""; }; + FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebViewDelegate.h; path = Classes/WebViewDelegate.h; sourceTree = ""; }; + FA3250C014BA85E700BF0781 /* WebViewDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = WebViewDelegate.m; path = Classes/WebViewDelegate.m; sourceTree = ""; }; + FA3250C814BA860800BF0781 /* App.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = App.h; path = Classes/Commands/App.h; sourceTree = ""; }; + FA3250C914BA860800BF0781 /* App.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Classes/Commands/App.m; sourceTree = ""; }; + FA3250CA14BA860800BF0781 /* Dock.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Dock.h; path = Classes/Commands/Dock.h; sourceTree = ""; }; + FA3250CB14BA860800BF0781 /* Dock.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Dock.m; path = Classes/Commands/Dock.m; sourceTree = ""; }; + FA3250CE14BA860800BF0781 /* Path.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Path.h; path = Classes/Commands/Path.h; sourceTree = ""; }; + FA3250CF14BA860800BF0781 /* Path.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Path.m; path = Classes/Commands/Path.m; sourceTree = ""; }; + FA3250D014BA860800BF0781 /* Sound.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Sound.h; path = Classes/Commands/Sound.h; sourceTree = ""; }; + FA3250D114BA860800BF0781 /* Sound.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Sound.m; path = Classes/Commands/Sound.m; sourceTree = ""; }; + FA3250E414BA883A00BF0781 /* public */ = {isa = PBXFileReference; lastKnownFileType = folder; path = public; sourceTree = ""; }; + FA3250E614BA8BCE00BF0781 /* application.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = application.icns; sourceTree = SOURCE_ROOT; }; + FA3F7741168F70780027B324 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.8.sdk/System/Library/Frameworks/Cocoa.framework; sourceTree = DEVELOPER_DIR; }; + FAE451BA14BA79C600190544 /* ZeroTier One.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ZeroTier One.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + FAE451BE14BA79C600190544 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; + FAE451C114BA79C600190544 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; + FAE451C214BA79C600190544 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; + FAE451C314BA79C600190544 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + FAE451C614BA79C600190544 /* MacGap-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MacGap-Info.plist"; sourceTree = ""; }; + FAE451C814BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; + FAE451CA14BA79C600190544 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MacGap-Prefix.pch"; sourceTree = ""; }; + FAE451CE14BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; + FAE451D014BA79C600190544 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + FAE451D114BA79C600190544 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + FAE451D414BA79C600190544 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/MainMenu.xib; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + FAE451B714BA79C600190544 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + C1C2B9911AFB0CF10060D7C2 /* Security.framework in Frameworks */, + 6F169DAC18CD8A4A005EDDF3 /* JavaScriptCore.framework in Frameworks */, + FA3F7742168F70790027B324 /* Cocoa.framework in Frameworks */, + FA32509D14BA813600BF0781 /* WebKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + FA3250E014BA87B800BF0781 /* Classes */ = { + isa = PBXGroup; + children = ( + FA3250E114BA87DD00BF0781 /* Commands */, + FA3250BA14BA85E700BF0781 /* Constants.h */, + 6F169DA818CC35FD005EDDF3 /* CallbackDelegate.h */, + 6F169DA918CC35FD005EDDF3 /* CallbackDelegate.m */, + FA3250BB14BA85E700BF0781 /* ContentView.h */, + FA3250BC14BA85E700BF0781 /* ContentView.m */, + FA3250BF14BA85E700BF0781 /* WebViewDelegate.h */, + FA3250C014BA85E700BF0781 /* WebViewDelegate.m */, + 88C0646B14BDF6A600E4BCE2 /* WindowController.h */, + 88C0646C14BDF6A600E4BCE2 /* WindowController.m */, + ); + name = Classes; + sourceTree = ""; + }; + FA3250E114BA87DD00BF0781 /* Commands */ = { + isa = PBXGroup; + children = ( + 6F169DA518CC332E005EDDF3 /* Command.h */, + 6F169DA618CC332E005EDDF3 /* Command.m */, + 1495814D15C15CCC00E1CFE5 /* Notice.h */, + 1495814E15C15CCC00E1CFE5 /* Notice.m */, + FA3250CA14BA860800BF0781 /* Dock.h */, + FA3250CB14BA860800BF0781 /* Dock.m */, + 6FD6E4EB18C2D48200DFFBE6 /* fonts.h */, + 6FD6E4EC18C2D48C00DFFBE6 /* fonts.m */, + FA3250BD14BA85E700BF0781 /* Utils.h */, + FA3250BE14BA85E700BF0781 /* Utils.m */, + 6FD672B418FE618E00C0DAAD /* UserDefaults.h */, + 6FD672B518FE618E00C0DAAD /* UserDefaults.m */, + FA3250CE14BA860800BF0781 /* Path.h */, + FA3250CF14BA860800BF0781 /* Path.m */, + FA3250D014BA860800BF0781 /* Sound.h */, + FA3250D114BA860800BF0781 /* Sound.m */, + FA3250C814BA860800BF0781 /* App.h */, + FA3250C914BA860800BF0781 /* App.m */, + 6F169DAD18CD906F005EDDF3 /* MenuItemProxy.h */, + 6F169DAE18CD906F005EDDF3 /* MenuItemProxy.m */, + 6F169DAF18CD906F005EDDF3 /* MenuProxy.h */, + 6F169DB018CD906F005EDDF3 /* MenuProxy.m */, + 88C0645E14BDE10A00E4BCE2 /* Window.h */, + 88C0645F14BDE10A00E4BCE2 /* Window.m */, + 88746BEC14CCA435001E160E /* JSEventHelper.h */, + 88746BED14CCA435001E160E /* JSEventHelper.m */, + F2B80014179E0FC100B069A8 /* Clipboard.h */, + F2B80015179E0FC100B069A8 /* Clipboard.m */, + ); + name = Commands; + sourceTree = ""; + }; + FAE451AF14BA79C600190544 = { + isa = PBXGroup; + children = ( + FA3F7741168F70780027B324 /* Cocoa.framework */, + FA3250E414BA883A00BF0781 /* public */, + FAE451C414BA79C600190544 /* MacGap */, + FAE451BD14BA79C600190544 /* Frameworks */, + FAE451BB14BA79C600190544 /* Products */, + ); + sourceTree = ""; + }; + FAE451BB14BA79C600190544 /* Products */ = { + isa = PBXGroup; + children = ( + FAE451BA14BA79C600190544 /* ZeroTier One.app */, + ); + name = Products; + sourceTree = ""; + }; + FAE451BD14BA79C600190544 /* Frameworks */ = { + isa = PBXGroup; + children = ( + C1C2B9901AFB0CF10060D7C2 /* Security.framework */, + 6F169DAB18CD8A4A005EDDF3 /* JavaScriptCore.framework */, + FA32509C14BA813600BF0781 /* WebKit.framework */, + FAE451BE14BA79C600190544 /* Cocoa.framework */, + FAE451C014BA79C600190544 /* Other Frameworks */, + ); + name = Frameworks; + sourceTree = ""; + }; + FAE451C014BA79C600190544 /* Other Frameworks */ = { + isa = PBXGroup; + children = ( + FAE451C114BA79C600190544 /* AppKit.framework */, + FAE451C214BA79C600190544 /* CoreData.framework */, + FAE451C314BA79C600190544 /* Foundation.framework */, + ); + name = "Other Frameworks"; + sourceTree = ""; + }; + FAE451C414BA79C600190544 /* MacGap */ = { + isa = PBXGroup; + children = ( + FA3250E014BA87B800BF0781 /* Classes */, + FAE451D014BA79C600190544 /* AppDelegate.h */, + FAE451D114BA79C600190544 /* AppDelegate.m */, + FAE451D314BA79C600190544 /* MainMenu.xib */, + 88C0646414BDEC5800E4BCE2 /* Window.xib */, + FAE451C514BA79C600190544 /* Supporting Files */, + ); + path = MacGap; + sourceTree = ""; + }; + FAE451C514BA79C600190544 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + FA3250E614BA8BCE00BF0781 /* application.icns */, + FAE451C614BA79C600190544 /* MacGap-Info.plist */, + FAE451C714BA79C600190544 /* InfoPlist.strings */, + FAE451CA14BA79C600190544 /* main.m */, + FAE451CC14BA79C600190544 /* MacGap-Prefix.pch */, + FAE451CD14BA79C600190544 /* Credits.rtf */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + FAE451B914BA79C600190544 /* MacGap */ = { + isa = PBXNativeTarget; + buildConfigurationList = FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */; + buildPhases = ( + FAE451B814BA79C600190544 /* Resources */, + FAE451B614BA79C600190544 /* Sources */, + FAE451B714BA79C600190544 /* Frameworks */, + FA3250DD14BA876F00BF0781 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = MacGap; + productName = MacGap; + productReference = FAE451BA14BA79C600190544 /* ZeroTier One.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + FAE451B114BA79C600190544 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0450; + ORGANIZATIONNAME = Twitter; + }; + buildConfigurationList = FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = FAE451AF14BA79C600190544; + productRefGroup = FAE451BB14BA79C600190544 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + FAE451B914BA79C600190544 /* MacGap */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + FAE451B814BA79C600190544 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + FA3250E514BA883A00BF0781 /* public in Resources */, + FAE451C914BA79C600190544 /* InfoPlist.strings in Resources */, + FAE451CF14BA79C600190544 /* Credits.rtf in Resources */, + FAE451D514BA79C600190544 /* MainMenu.xib in Resources */, + FA3250E714BA8BCE00BF0781 /* application.icns in Resources */, + 88C0646614BDEC5800E4BCE2 /* Window.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + FAE451B614BA79C600190544 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 6F169DAA18CC35FD005EDDF3 /* CallbackDelegate.m in Sources */, + FA3250D314BA860800BF0781 /* App.m in Sources */, + FA3250D514BA860800BF0781 /* Dock.m in Sources */, + FA3250D914BA860800BF0781 /* Path.m in Sources */, + FA3250DB14BA860800BF0781 /* Sound.m in Sources */, + FA3250C314BA85E700BF0781 /* ContentView.m in Sources */, + FA3250C514BA85E700BF0781 /* Utils.m in Sources */, + FA3250C714BA85E700BF0781 /* WebViewDelegate.m in Sources */, + FAE451CB14BA79C600190544 /* main.m in Sources */, + 6F169DB118CD906F005EDDF3 /* MenuItemProxy.m in Sources */, + FAE451D214BA79C600190544 /* AppDelegate.m in Sources */, + 6F169DA718CC332E005EDDF3 /* Command.m in Sources */, + 6FD672B618FE618E00C0DAAD /* UserDefaults.m in Sources */, + 88C0646014BDE10A00E4BCE2 /* Window.m in Sources */, + 6F169DB218CD906F005EDDF3 /* MenuProxy.m in Sources */, + 88C0646D14BDF6A600E4BCE2 /* WindowController.m in Sources */, + 6FD6E4ED18C2D48C00DFFBE6 /* fonts.m in Sources */, + 88746BEE14CCA435001E160E /* JSEventHelper.m in Sources */, + 1495814F15C15CCC00E1CFE5 /* Notice.m in Sources */, + F2B80016179E0FC100B069A8 /* Clipboard.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + 88C0646414BDEC5800E4BCE2 /* Window.xib */ = { + isa = PBXVariantGroup; + children = ( + 88C0646514BDEC5800E4BCE2 /* en */, + ); + name = Window.xib; + sourceTree = ""; + }; + FAE451C714BA79C600190544 /* InfoPlist.strings */ = { + isa = PBXVariantGroup; + children = ( + FAE451C814BA79C600190544 /* en */, + ); + name = InfoPlist.strings; + sourceTree = ""; + }; + FAE451CD14BA79C600190544 /* Credits.rtf */ = { + isa = PBXVariantGroup; + children = ( + FAE451CE14BA79C600190544 /* en */, + ); + name = Credits.rtf; + sourceTree = ""; + }; + FAE451D314BA79C600190544 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + FAE451D414BA79C600190544 /* en */, + ); + name = MainMenu.xib; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + FAE451D614BA79C600190544 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = ""; + }; + name = Debug; + }; + FAE451D714BA79C600190544 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_ENABLE_OBJC_ARC = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = ""; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = ""; + }; + name = Release; + }; + FAE451D914BA79C600190544 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MacGap\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; + GCC_VERSION = ""; + INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = macosx; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + FAE451DA14BA79C600190544 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "compiler-default"; + CLANG_CXX_LIBRARY = "compiler-default"; + COMBINE_HIDPI_IMAGES = YES; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/MacGap\"", + ); + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "MacGap/MacGap-Prefix.pch"; + GCC_VERSION = ""; + INFOPLIST_FILE = "MacGap/MacGap-Info.plist"; + MACOSX_DEPLOYMENT_TARGET = 10.7; + PRODUCT_NAME = "ZeroTier One"; + SDKROOT = macosx; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + FAE451B414BA79C600190544 /* Build configuration list for PBXProject "MacGap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FAE451D614BA79C600190544 /* Debug */, + FAE451D714BA79C600190544 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + FAE451D814BA79C600190544 /* Build configuration list for PBXNativeTarget "MacGap" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + FAE451D914BA79C600190544 /* Debug */, + FAE451DA14BA79C600190544 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = FAE451B114BA79C600190544 /* Project object */; +} diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 000000000..88f36fc7b --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout new file mode 100644 index 000000000..b2ea215df --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcshareddata/MacGap.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 4D486E78-E297-4CC3-AAAE-1A58EDAC87E6 + IDESourceControlProjectName + MacGap + IDESourceControlProjectOriginsDictionary + + 60776BB1B4F98ABFCF3BD8223221516D7FB415ED + https://github.com/MacGapProject/MacGap1.git + + IDESourceControlProjectPath + MacGap.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + 60776BB1B4F98ABFCF3BD8223221516D7FB415ED + ../.. + + IDESourceControlProjectURL + https://github.com/MacGapProject/MacGap1.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 60776BB1B4F98ABFCF3BD8223221516D7FB415ED + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 60776BB1B4F98ABFCF3BD8223221516D7FB415ED + IDESourceControlWCCName + MacGap1 + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/Alex.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..20281812beaefed26ed5a7ceb16e431be71ad75f GIT binary patch literal 46675 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 IMozN_0249hqyPW_ literal 0 HcmV?d00001 diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/UserInterfaceState.xcuserstate b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/api.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..04ade238606e9d7a8d4efba88066f44ffaac7322 GIT binary patch literal 18268 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 SCMF2Y2I + + + + HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..822ed3cb6581b8e606bab5208852eff2f504b0a4 GIT binary patch literal 27811 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 literal 0 HcmV?d00001 diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings new file mode 100644 index 000000000..6ff33e603 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/project.xcworkspace/xcuserdata/liamks.xcuserdatad/WorkspaceSettings.xcsettings @@ -0,0 +1,10 @@ + + + + + IDEWorkspaceUserSettings_HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges + + IDEWorkspaceUserSettings_SnapshotAutomaticallyBeforeSignificantChanges + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist new file mode 100644 index 000000000..38f661269 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MacGap.xcscheme b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MacGap.xcscheme new file mode 100644 index 000000000..0aaad5827 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/MacGap.xcscheme @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..921f1a6fe --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/Alex.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + MacGap.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + FAE451B914BA79C600190544 + + primary + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist new file mode 100644 index 000000000..fe2b45415 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -0,0 +1,5 @@ + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/MacGap.xcscheme b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/MacGap.xcscheme new file mode 100644 index 000000000..2555dc89c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/MacGap.xcscheme @@ -0,0 +1,88 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/xcschememanagement.plist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..921f1a6fe --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/api.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + MacGap.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + FAE451B914BA79C600190544 + + primary + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist new file mode 100644 index 000000000..8e541eaba --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist @@ -0,0 +1,161 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/MacGap.xcscheme b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/MacGap.xcscheme new file mode 100644 index 000000000..872d6d7d5 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/MacGap.xcscheme @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/xcschememanagement.plist b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 000000000..921f1a6fe --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap.xcodeproj/xcuserdata/liamks.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + MacGap.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + FAE451B914BA79C600190544 + + primary + + + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.h b/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.h new file mode 100644 index 000000000..bf7370b50 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.h @@ -0,0 +1,18 @@ +// +// AppDelegate.h +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "Classes/ContentView.h" + +#import "WindowController.h" + +@interface AppDelegate : NSObject + +@property (retain, nonatomic) WindowController *windowController; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.m b/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.m new file mode 100644 index 000000000..96a3e8201 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/AppDelegate.m @@ -0,0 +1,110 @@ +// +// AppDelegate.m +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "AppDelegate.h" + +@implementation AppDelegate + +@synthesize windowController; + +- (void) applicationWillFinishLaunching:(NSNotification *)aNotification +{ +} + +-(BOOL)applicationShouldHandleReopen:(NSApplication*)application + hasVisibleWindows:(BOOL)visibleWindows{ + if(!visibleWindows){ + [self.windowController.window makeKeyAndOrderFront: nil]; + } + return YES; +} + +- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication { + return YES; +} + +- (void) applicationDidFinishLaunching:(NSNotification *)aNotification { + // Create authorization reference + OSStatus status; + AuthorizationRef authorizationRef; + + // AuthorizationCreate and pass NULL as the initial + // AuthorizationRights set so that the AuthorizationRef gets created + // successfully, and then later call AuthorizationCopyRights to + // determine or extend the allowable rights. + // http://developer.apple.com/qa/qa2001/qa1172.html + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &authorizationRef); + if (status != errAuthorizationSuccess) + { + NSLog(@"Error Creating Initial Authorization: %d", status); + return; + } + + // kAuthorizationRightExecute == "system.privilege.admin" + AuthorizationItem right = {kAuthorizationRightExecute, 0, NULL, 0}; + AuthorizationRights rights = {1, &right}; + AuthorizationFlags flags = kAuthorizationFlagDefaults | kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagPreAuthorize | kAuthorizationFlagExtendRights; + + // Call AuthorizationCopyRights to determine or extend the allowable rights. + status = AuthorizationCopyRights(authorizationRef, &rights, NULL, flags, NULL); + if (status != errAuthorizationSuccess) + { + NSLog(@"Copy Rights Unsuccessful: %d", status); + return; + } + + // use rm tool with -rf + char *tool = "/bin/cat"; + char *args[] = {"/Library/Application Support/ZeroTier/One/authtoken.secret", NULL}; + FILE *pipe = NULL; + + status = AuthorizationExecuteWithPrivileges(authorizationRef, tool, kAuthorizationFlagDefaults, args, &pipe); + if (status != errAuthorizationSuccess) + { + NSLog(@"Error: %d", status); + } + + char url[16384]; + memset(url,0,sizeof(url)); + if (pipe) { + char buf[16384]; + + FILE *pf = fopen("/Library/Application Support/ZeroTier/One/zerotier-one.port","r"); + long n = fread(buf,1,sizeof(buf)-1,pf); + long port = 9993; // default + if (n > 0) { + buf[n] = (char)0; + port = strtol(buf,(char **)0,10); + } + fclose(pf); + + n = (long)fread(buf,1,sizeof(buf)-1,pipe); + if (n > 0) { + buf[n] = (char)0; + snprintf(url,sizeof(url),"http://127.0.0.1:%ld/index.html?authToken=%s",port,buf); + } + fclose(pipe); + } + + // The only way to guarantee that a credential acquired when you + // request a right is not shared with other authorization instances is + // to destroy the credential. To do so, call the AuthorizationFree + // function with the flag kAuthorizationFlagDestroyRights. + // http://developer.apple.com/documentation/Security/Conceptual/authorization_concepts/02authconcepts/chapter_2_section_7.html + status = AuthorizationFree(authorizationRef, kAuthorizationFlagDestroyRights); + + NSString *urlStr = [[NSString alloc] initWithCString:url]; + self.windowController = [[WindowController alloc] initWithURL: urlStr]; + [self.windowController showWindow: [NSApplication sharedApplication].delegate]; + self.windowController.contentView.webView.alphaValue = 1.0; + self.windowController.contentView.alphaValue = 1.0; + [self.windowController showWindow:self]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.h new file mode 100755 index 000000000..0f31ee417 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.h @@ -0,0 +1,20 @@ +// +// CallbackDelegate.h +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" + +@interface CallbackDelegate : Command { +} + +@property JSObjectRef callback; + +- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback; +- (id) call; +- (id) callWithParams:(id)firstOrNil, ... NS_REQUIRES_NIL_TERMINATION; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.m new file mode 100755 index 000000000..5ce8fbe33 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/CallbackDelegate.m @@ -0,0 +1,168 @@ +// +// CallbackDelegate.m +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "CallbackDelegate.h" +#import + +@implementation CallbackDelegate + +@synthesize callback; + +- (id) initWithContext:(JSContextRef)aContext forCallback:(WebScriptObject*)aCallback +{ + if (!aCallback) + return nil; + if ([aCallback isKindOfClass:[WebUndefined class]]) + return nil; + + self = [super initWithContext:aContext]; + if (!self) + return nil; + + callback = [aCallback JSObject]; + JSValueProtect(context, callback); + return self; +} + +- (void) dealloc +{ + if (callback) + { + JSValueUnprotect(context, callback); + callback = nil; + } +} + +- (id) objectFromValue:(JSValueRef)val +{ + JSStringRef jstr; + NSString *rets; + + switch(JSValueGetType(context, val)) + { + case kJSTypeUndefined: + case kJSTypeNull: + return nil; + case kJSTypeBoolean: + return [NSNumber numberWithBool:JSValueToBoolean(context, val)]; + case kJSTypeNumber: + return [NSNumber numberWithDouble:JSValueToNumber(context, val, NULL)]; + case kJSTypeString: + jstr = JSValueToStringCopy(context, val, NULL); + size_t sz = JSStringGetMaximumUTF8CStringSize(jstr); + char *buf = (char*)malloc(sz); + JSStringGetUTF8CString(jstr, buf, sz); + rets = [NSString stringWithUTF8String:buf]; + free(buf); + return rets; + case kJSTypeObject: + // TODO: dictionary or something + return nil; + default: + NSAssert(false, @"Invalid JavaScript type"); + return nil; + } +} + +- (JSValueRef) valueFromObject:(id)obj +{ + JSValueRef val = nil; + if (!obj) + { + val = JSValueMakeNull(context); + } + else if ([obj isKindOfClass:[NSString class]]) + { + JSStringRef jstr = JSStringCreateWithUTF8CString([obj UTF8String]); + val = JSValueMakeString(context, jstr); + JSStringRelease(jstr); + } + else if ([obj isKindOfClass:[NSNumber class]]) + { + val = JSValueMakeNumber(context, [obj doubleValue]); + } + else if ([obj isKindOfClass:[NSDictionary class]]) + { + JSObjectRef o = JSObjectMake(context, NULL, NULL); + for (NSString *key in obj) + { + JSStringRef kstr = JSStringCreateWithUTF8CString([key UTF8String]); + JSValueRef v = [self valueFromObject:[obj objectForKey:key]]; + + JSObjectSetProperty(context, o, kstr, v, kJSPropertyAttributeNone, NULL); + JSStringRelease(kstr); + } + val = o; + } + else if ([obj isKindOfClass:[NSArray class]]) + { + NSUInteger pcount = [obj count]; + JSValueRef jsArgs[pcount]; + NSUInteger i=0; + for (id v in obj) + { + jsArgs[i++] = [self valueFromObject:v]; + } + val = JSObjectMakeArray(context, pcount, jsArgs, NULL); + } + else if ([obj isKindOfClass:[NSDate class]]) + { + NSTimeInterval secs = [obj timeIntervalSince1970]; + JSValueRef jsArgs[1]; + // call the Date(milliseconds) constructor in JS + jsArgs[0] = JSValueMakeNumber(context, secs * 1000.0); + val = JSObjectMakeDate(context, 1, jsArgs, NULL); + } + else + { + NSLog(@"Warning: unknown object type for: %@", obj); + val = JSValueMakeUndefined(context); + } + return val; +} + +- (id) call +{ + NSAssert(callback, @"Callback required"); + if (!JSObjectIsFunction(context, callback)) + return nil; + + JSValueRef jsArgs[0]; + JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, 0, jsArgs, NULL); + return [self objectFromValue:ret]; +} + +- (id) callWithParams:(id)firstOrNil, ... +{ + NSAssert(callback, @"Callback required"); + if (!JSObjectIsFunction(context, callback)) + return nil; + NSUInteger pcount = 0; + id p; + va_list args; + va_start(args, firstOrNil); + for (p=firstOrNil; p; p=va_arg(args, id)) + { + pcount++; + } + va_end(args); + + JSValueRef jsArgs[pcount]; + NSUInteger j = 0; + va_start(args, firstOrNil); + for (p=firstOrNil; p; p=va_arg(args, id)) + { + jsArgs[j++] = [self valueFromObject:p]; + } + va_end(args); + + JSValueRef ret = JSObjectCallAsFunction(context, callback, NULL, j, jsArgs, NULL); + return [self objectFromValue:ret]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.h new file mode 100644 index 000000000..f65ba61e1 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.h @@ -0,0 +1,21 @@ +#import + +#import "WindowController.h" + +@interface App : NSObject { + +} + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; + +- (void) terminate; +- (void) activate; +- (void) hide; +- (void) unhide; +- (void) beep; +- (void) bounce; +- (void) setCustomUserAgent:(NSString *)userAgentString; +- (NSNumber*) systemIdleTime; +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.m new file mode 100644 index 000000000..6d47a17e1 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/App.m @@ -0,0 +1,128 @@ +#import "App.h" + +#import "JSEventHelper.h" + +@implementation App + +@synthesize webView; + +- (id) initWithWebView:(WebView *) view{ + self = [super init]; + + if (self) { + self.webView = view; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveSleepNotification:) + name: NSWorkspaceWillSleepNotification object: NULL]; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveWakeNotification:) + name: NSWorkspaceDidWakeNotification object: NULL]; + [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver: self + selector: @selector(receiveActivateNotification:) + name: NSWorkspaceDidActivateApplicationNotification object: NULL]; + } + + return self; +} + +- (void) terminate { + [NSApp terminate:nil]; +} + +- (void) activate { + [NSApp activateIgnoringOtherApps:YES]; +} + +- (void) hide { + [NSApp hide:nil]; +} + +- (void) unhide { + [NSApp unhide:nil]; +} + +- (void)beep { + NSBeep(); +} + +- (void) bounce { + [NSApp requestUserAttention:NSInformationalRequest]; +} + +- (void)setCustomUserAgent:(NSString *)userAgentString { + [self.webView setCustomUserAgent: userAgentString]; +} + +- (void) open:(NSString*)url { + [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:url]]; +} + +- (void) launch:(NSString *)name { + [[NSWorkspace sharedWorkspace] launchApplication:name]; +} + +- (void)receiveSleepNotification:(NSNotification*)note{ + [JSEventHelper triggerEvent:@"sleep" forWebView:self.webView]; +} + +- (void) receiveWakeNotification:(NSNotification*)note{ + [JSEventHelper triggerEvent:@"wake" forWebView:self.webView]; +} + +- (void) receiveActivateNotification:(NSNotification*)notification{ + NSDictionary* userInfo = [notification userInfo]; + NSRunningApplication* runningApplication = [userInfo objectForKey:NSWorkspaceApplicationKey]; + if (runningApplication) { + NSMutableDictionary* applicationDidGetFocusDict = [[NSMutableDictionary alloc] initWithCapacity:2]; + [applicationDidGetFocusDict setObject:runningApplication.localizedName + forKey:@"localizedName"]; + [applicationDidGetFocusDict setObject:[runningApplication.bundleURL absoluteString] + forKey:@"bundleURL"]; + + [JSEventHelper triggerEvent:@"appActivated" withArgs:applicationDidGetFocusDict forWebView:self.webView]; + } +} + + + + +/* + To get the elapsed time since the previous input event—keyboard, mouse, or tablet—specify kCGAnyInputEventType. + */ +- (NSNumber*)systemIdleTime { + CFTimeInterval timeSinceLastEvent = CGEventSourceSecondsSinceLastEventType(kCGEventSourceStateHIDSystemState, kCGAnyInputEventType); + + return [NSNumber numberWithDouble:timeSinceLastEvent]; +} + + + + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(open:)) { + result = @"open"; + } else if (selector == @selector(launch:)) { + result = @"launch"; + } else if (selector == @selector(setCustomUserAgent:)) { + result = @"setCustomUserAgent"; + } else if (selector == @selector(systemIdleTime)) { + result = @"systemIdleTime"; + } + + return result; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.h new file mode 100755 index 000000000..65d6b6d48 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.h @@ -0,0 +1,18 @@ +// +// Command.h +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import + +@interface Command : NSObject { + JSContextRef context; +} + +- (id) initWithContext:(JSContextRef)aContext; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.m new file mode 100755 index 000000000..39b85630a --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Command.m @@ -0,0 +1,28 @@ +// +// Command.m +// MacGap +// +// Created by Joe Hildebrand on 1/10/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" +#import + +@implementation Command + +- (id) initWithContext:(JSContextRef)aContext { + self = [super init]; + if (!self) + return nil; + context = aContext; + JSGlobalContextRetain((JSGlobalContextRef)context); + return self; +} + +- (void)dealloc +{ + if (context) + JSGlobalContextRelease((JSGlobalContextRef)context); +} +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.h new file mode 100644 index 000000000..b3c533d79 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.h @@ -0,0 +1,11 @@ +#import + +@interface Dock : NSObject { + +} +- (void) setBadge:(NSString*)value; +- (NSString *) badge; + +@property (readwrite, copy) NSString *badge; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.m new file mode 100644 index 000000000..a4494d165 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Dock.m @@ -0,0 +1,31 @@ +#import "Dock.h" + +@implementation Dock + +@synthesize badge; + +- (void) setBadge:(NSString *)value +{ + NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; + [tile setBadgeLabel:value]; +} + +- (NSString *) badge +{ + NSDockTile *tile = [[NSApplication sharedApplication] dockTile]; + return [tile badgeLabel]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.h new file mode 100755 index 000000000..d765978fa --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.h @@ -0,0 +1,31 @@ +// +// MenuItemProxy.h +// MacGap +// +// Created by Joe Hildebrand on 1/15/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" +#import "CallbackDelegate.h" + +@class MenuProxy; + +@interface MenuItemProxy : Command { + NSMenuItem *item; + CallbackDelegate *callback; +} + ++ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem; + +- (MenuProxy*)addSubmenu; + +- (void) remove; +- (void) setCallback:(WebScriptObject*)aCallback; +- (void) setKey:(NSString*)keyCommand; +- (void) setTitle:(NSString*)title; +- (void) enable; +- (void) disable; +- (MenuProxy*)submenu; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.m new file mode 100755 index 000000000..7b9702cc4 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuItemProxy.m @@ -0,0 +1,150 @@ +// +// MenuItemProxy.m +// MacGap +// +// Created by Joe Hildebrand on 1/15/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "MenuItemProxy.h" +#import "MenuProxy.h" + +@implementation MenuItemProxy + +- (id) initWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem +{ + NSAssert(anItem, @"anItem required"); + self = [super initWithContext:aContext]; + if (!self) + return nil; + item = anItem; + item.representedObject = self; + + return self; +} + ++ (MenuItemProxy*) proxyWithContext:(JSContextRef)aContext andMenuItem:(NSMenuItem*)anItem +{ + MenuItemProxy *proxy = [anItem representedObject]; + if (proxy) + { + NSLog(@"MIP Cache hit"); + NSAssert([proxy class] == [MenuItemProxy class], @"Bad proxy"); + return proxy; + } + return [[MenuItemProxy alloc] initWithContext:aContext andMenuItem:anItem]; +} + +- (NSString*) description +{ + return [item description]; +} + +- (MenuProxy*)addSubmenu +{ + NSMenu *s = [item submenu]; + if (!s) + { + s = [[NSMenu alloc] initWithTitle:@"FFFFFFOOOOO"]; + [item setSubmenu:s]; + } + return [MenuProxy proxyWithContext:context andMenu:s]; +} + +- (void) remove +{ + NSMenu *menu = [item menu]; + [menu removeItem:item]; +} + +- (void)callCallback:(id)sender +{ + [callback callWithParams:[sender title], nil]; +} + +- (void) setCallback:(WebScriptObject*)aCallback +{ + NSAssert(item, @"item required"); + callback = [[CallbackDelegate alloc] initWithContext:context forCallback:aCallback]; + [item setAction:@selector(callCallback:)]; + [item setTarget:self]; +} + +- (void)setKey:(NSString*)keyCommand +{ + NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; + [item setKeyEquivalent:aKey]; + + NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; + [item setKeyEquivalentModifierMask:modifiers]; +} + +- (void) setTitle:(NSString*)title +{ + [item setTitle:title]; +} + +- (MenuProxy*)submenu; +{ + // TODO: make this work as a property + NSMenu *s = [item submenu]; + if (!s) + return nil; + return [MenuProxy proxyWithContext:context andMenu:s]; +} + +- (void) enable +{ + [item setEnabled:YES]; +} + +- (void) disable +{ + [item setEnabled:NO]; +} + +#pragma mark WebScripting protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(addSubmenu)) { + result = @"addSubmenu"; + } + else if (selector == @selector(remove)) { + result = @"remove"; + } + else if (selector == @selector(setCallback:)) { + result = @"setCallback"; + } + else if (selector == @selector(setKey:)) { + result = @"setKey"; + } + else if (selector == @selector(setTitle:)) { + result = @"setTitle"; + } + else if (selector == @selector(submenu)) { + result = @"submenu"; + } + else if (selector == @selector(enable)) { + result = @"enable"; + } + else if (selector == @selector(disable)) { + result = @"disable"; + } + + return result; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.h new file mode 100755 index 000000000..afd6c6edb --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.h @@ -0,0 +1,31 @@ +// +// MenuProxy.h +// MacGap +// +// Created by Joe Hildebrand on 1/14/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Command.h" + +@class MenuItemProxy; + +@interface MenuProxy : Command { + NSMenu *menu; +} + ++ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu; + +- (MenuItemProxy*)addItemWithTitle:(NSString*)title + keyEquivalent:(NSString*)aKey + callback:(WebScriptObject*)aCallback + atIndex:(NSInteger)index; + +- (MenuItemProxy*)addSeparator; +- (MenuItemProxy*)itemForKey:(id)key; +- (MenuProxy*)removeItem:(id)key; + ++ (NSString*)getKeyFromString:(NSString*)keyCommand; ++ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.m new file mode 100755 index 000000000..5bc10a763 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/MenuProxy.m @@ -0,0 +1,233 @@ +// +// MenuProxy.m +// MacGap +// +// Created by Joe Hildebrand on 1/14/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import + +#import "MenuProxy.h" +#import "MenuItemProxy.h" + +static char REPRESENTED_OBJECT; + +@interface NSMenu (represented) +@property (strong) id representedObject; +@end + +@implementation NSMenu (represented) + +- (id) representedObject +{ + return objc_getAssociatedObject(self, &REPRESENTED_OBJECT); +} + +- (void) setRepresentedObject:(id)representedObject +{ + objc_setAssociatedObject(self, + &REPRESENTED_OBJECT, + representedObject, + OBJC_ASSOCIATION_RETAIN); +} + +@end + +@implementation MenuProxy + +- (id) initWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu +{ + self = [super initWithContext:aContext]; + if (!self) + return nil; + menu = aMenu; + menu.representedObject = self; + return self; +} + ++ (MenuProxy*)proxyWithContext:(JSContextRef)aContext andMenu:(NSMenu*)aMenu +{ + // singleton-ish. + MenuProxy *ret = [aMenu representedObject]; + if (ret) + { + NSLog(@"MP cache hit"); + return ret; + } + return [[MenuProxy alloc] initWithContext:aContext andMenu:aMenu]; +} + +- (void) dealloc +{ + menu.representedObject = nil; +} + +- (NSString*) description +{ + return [menu description]; +} + +static BOOL isNullish(id o) +{ + if (!o) + return YES; + if ([o isKindOfClass:[WebUndefined class]]) + return YES; + return NO; +} + +- (MenuItemProxy*)addItemWithTitle:(NSString*)title + keyEquivalent:(NSString*)keyCommand + callback:(WebScriptObject*)aCallback + atIndex:(NSInteger)index +{ + if (isNullish(title)) + title = @""; + + NSString *aKey = [MenuProxy getKeyFromString:keyCommand]; + NSMenuItem *item = nil; + + if(index) { + item = [menu insertItemWithTitle:title action:nil keyEquivalent:aKey atIndex:index ]; + } else { + item = [menu addItemWithTitle:title action:nil keyEquivalent:aKey ]; + + } + + // Set the modifiers. + NSUInteger modifiers = [MenuProxy getModifiersFromString:keyCommand]; + [item setKeyEquivalentModifierMask:modifiers]; + + if(!menu.supermenu) { + NSMenu *s = [[NSMenu alloc] initWithTitle:title]; + [item setSubmenu:s]; + } + + MenuItemProxy *mip = [MenuItemProxy proxyWithContext:context andMenuItem:item]; + if (!isNullish(aCallback)) + [mip setCallback:aCallback]; + + + return mip; +} + ++ (NSString*)getKeyFromString:(NSString*)keyCommand { + if (isNullish(keyCommand)) + keyCommand = @""; + + // Obtain the key (if there are modifiers, it will be the last character). + NSString *aKey = @""; + if ([keyCommand length] > 0) { + aKey = [keyCommand substringFromIndex:[keyCommand length] - 1]; + } + + return aKey; +} + ++ (NSUInteger*)getModifiersFromString:(NSString*)keyCommand { + // aKeys may optionally specify one or more modifiers. + NSUInteger modifiers = 0; + + if ([keyCommand rangeOfString:@"caps"].location != NSNotFound) modifiers += NSAlphaShiftKeyMask; + if ([keyCommand rangeOfString:@"shift"].location != NSNotFound) modifiers += NSShiftKeyMask; + if ([keyCommand rangeOfString:@"cmd"].location != NSNotFound) modifiers += NSCommandKeyMask; + if ([keyCommand rangeOfString:@"ctrl"].location != NSNotFound) modifiers += NSControlKeyMask; + if ([keyCommand rangeOfString:@"opt"].location != NSNotFound) modifiers += NSAlternateKeyMask; + if ([keyCommand rangeOfString:@"alt"].location != NSNotFound) modifiers += NSAlternateKeyMask; + + return modifiers; +} + +- (MenuItemProxy*)addSeparator +{ + NSMenuItem *sep = [NSMenuItem separatorItem]; + [menu addItem:sep]; + return [MenuItemProxy proxyWithContext:context andMenuItem:sep]; +} + +- (MenuItemProxy*)itemForKey:(id)key +{ + if (isNullish(key)) + return nil; + NSMenuItem *item = nil; + if ([key isKindOfClass:[NSNumber class]]) + { + item = [menu itemAtIndex:[key intValue]]; + } + else if ([key isKindOfClass:[NSString class]]) + { + item = [menu itemWithTitle:key]; + if (!item) + { + // Try again, with ... appended. e.g. "Save..." + item = [menu itemWithTitle: + [key stringByAppendingString:@"\u2026"]]; + } + } + if (!item) + return nil; + + return [MenuItemProxy proxyWithContext:context andMenuItem:item]; +} + +- (MenuProxy*)removeItem:(id)key +{ + if (isNullish(key)) + return nil; + + NSMenuItem *item = nil; + if ([key isKindOfClass:[NSNumber class]]) + { + item = [menu itemAtIndex:[key intValue]]; + } + else if ([key isKindOfClass:[NSString class]]) + { + item = [menu itemWithTitle:key]; + if (!item) + { + // Try again, with ... appended. e.g. "Save..." + item = [menu itemWithTitle: + [key stringByAppendingString:@"\u2026"]]; + } + } + if (!item) + return nil; + + [menu removeItem:item]; + return [MenuProxy proxyWithContext:context andMenu:menu]; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(addItemWithTitle:keyEquivalent:callback:atIndex:)) { + result = @"addItem"; + } + else if (selector == @selector(addSeparator)) { + result = @"addSeparator"; + } + else if (selector == @selector(itemForKey:)) { + result = @"getItem"; + } + else if (selector == @selector(removeItem:)) { + result = @"removeMenu"; + } + + return result; +} + + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.h new file mode 100644 index 000000000..51077a434 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.h @@ -0,0 +1,26 @@ +// +// Notice.h +// MacGap +// +// Created by Christian Sullivan on 7/26/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "WindowController.h" + +#define APP_NOTICE_NOTIFICATION @"Notice" + +@interface Notice : NSObject { + +} + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (void) notify:(NSDictionary*)message; +- (void) close:(NSString*)notificationId; ++ (BOOL) available; + +@end + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.m new file mode 100644 index 000000000..a4095f9f2 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Notice.m @@ -0,0 +1,108 @@ +// +// Notice.m +// MacGap +// +// Created by Christian Sullivan on 7/26/12. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "Notice.h" + +#import "JSEventHelper.h" + +@implementation Notice + +- (id) initWithWebView:(WebView*)view +{ + if(self = [super init]) { + self.webView = view; + [[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:self]; + } + return self; +} + +- (void) notify:(NSDictionary *)message { + NSUserNotification *notification = [[NSUserNotification alloc] init]; + [notification setTitle:[message valueForKey:@"title"]]; + [notification setInformativeText:[message valueForKey:@"content"]]; + [notification setDeliveryDate:[NSDate dateWithTimeInterval:0 sinceDate:[NSDate date]]]; + BOOL playSound = true; // optional parameter, false only when {sound: false} + @try { + NSNumber *s = [message valueForKey:@"sound"]; + if ([[s className] isEqual: @"__NSCFBoolean"]) { + playSound = [s boolValue]; + } + } + @catch (NSException *exception) { + } + if (playSound) { + [notification setSoundName:NSUserNotificationDefaultSoundName]; + } + NSString *id = @""; // optional, needed for close + @try { + id = [message valueForKey:@"id"]; + } + @catch (NSException *exception) { + } + [notification setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys:id, @"id", nil]]; + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + [center scheduleNotification:notification]; +} + +// close all notifications with id == notificationId or close all notifications if notificationId == "*" +- (void) close:(NSString*)notificationId { + NSUserNotificationCenter *center = [NSUserNotificationCenter defaultUserNotificationCenter]; + for(NSUserNotification * deliveredNote in center.deliveredNotifications) { + if ([notificationId isEqualToString:@"*"] || [deliveredNote.userInfo[@"id"] isEqualToString:notificationId]) { + [center removeDeliveredNotification: deliveredNote]; + } + } +} + ++ (BOOL) available { + if ([NSUserNotificationCenter respondsToSelector:@selector(defaultUserNotificationCenter)]) + return YES; + + return NO; +} + +- (void) userNotificationCenter:(NSUserNotificationCenter *)center didActivateNotification:(NSUserNotification *)notification +{ + NSString *notificationId = [notification.userInfo valueForKey:@"id"]; + [JSEventHelper triggerEvent:@"macgap.notify.activated" forDetail:notificationId forWebView:self.webView]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + BOOL result = YES; + if (selector == @selector(notify:)) + result = NO; + if (selector == @selector(close:)) + result = NO; + + return result; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(notify:)) { + result = @"notify"; + } + if (selector == @selector(close:)) { + result = @"close"; + } + + return result; +} + +// right now exclude all properties (eg keys) ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.h new file mode 100644 index 000000000..f931340d0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.h @@ -0,0 +1,21 @@ +#import + +@interface Path : NSObject { + +} + +- (NSString *) application; +- (NSString *) resource; +- (NSString *) documents; +- (NSString *) library; +- (NSString *) home; +- (NSString *) temp; + +@property (readonly,copy) NSString* application; +@property (readonly,copy) NSString* resource; +@property (readonly,copy) NSString* documents; +@property (readonly,copy) NSString* library; +@property (readonly,copy) NSString* home; +@property (readonly,copy) NSString* temp; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.m new file mode 100644 index 000000000..8c54100f7 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Path.m @@ -0,0 +1,53 @@ +#import "Path.h" + +@implementation Path + +@synthesize application; +@synthesize resource; +@synthesize documents; +@synthesize library; +@synthesize home; +@synthesize temp; + +- (NSString *)application { + return [[NSBundle mainBundle] bundlePath]; +} + +- (NSString *)resource { + return [[NSBundle mainBundle] resourcePath]; +} + +- (NSString *)documents { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + return [paths objectAtIndex:0]; +} + +- (NSString *)library { + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES); + NSLog( @"%@", paths ); + return [paths objectAtIndex:0]; +} + +- (NSString *)home { + return NSHomeDirectory(); +} + +- (NSString *)temp { + return NSTemporaryDirectory(); +} + +#pragma mark WebScripting Protocol + +/* checks whether a selector is acceptable to be called from JavaScript */ ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + +// right now exclude all properties (eg keys) ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.h new file mode 100644 index 000000000..067076439 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.h @@ -0,0 +1,17 @@ +#import +#import "Command.h" +#import "CallbackDelegate.h" + + +@interface Sound : Command { + +} + +// pending callbacks for sounds being played, to keep +// ARC from freeing them too early +@property (nonatomic, strong) NSMutableSet *pending; + +- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback; +- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.m new file mode 100644 index 000000000..9f4a44dbc --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/Sound.m @@ -0,0 +1,97 @@ +#import "Sound.h" + + +@interface PlayDelegate : CallbackDelegate { +} + +@property (nonatomic, weak) Sound *sound; + +- (id) initWithContext:(JSContextRef)aContext + forCallback:(WebScriptObject*)aCallback + withSound:(Sound*)aSound; +@end + +@implementation PlayDelegate + +@synthesize sound; + +- (id) initWithContext:(JSContextRef)aContext + forCallback:(WebScriptObject*)aCallback + withSound:(Sound*)aSound +{ + self = [super initWithContext:aContext forCallback:aCallback]; + if (!self) + return nil; + sound = aSound; + return self; +} + +- (void)sound:(NSSound *)aSound didFinishPlaying:(BOOL)finishedPlaying { + [self callWithParams:[aSound name], nil]; + [sound.pending removeObject:self]; +} + +@end + +@implementation Sound + +@synthesize pending; + +- (id) initWithContext:(JSContextRef)aContext { + self = [super initWithContext:aContext]; + if (!self) { + return nil; + } + + pending = [NSMutableSet new]; + return self; +} + +- (void) playSound:(NSSound*)sound onComplete:(WebScriptObject*)callback { + if (callback != (id)[WebUndefined undefined]) { + PlayDelegate *d = [[PlayDelegate alloc] initWithContext:context + forCallback:callback + withSound:self]; + [pending addObject:d]; + [sound setDelegate:d]; + } + [sound play]; +} + +- (void) play:(NSString*)file onComplete:(WebScriptObject*)callback { + NSURL* fileUrl = [NSURL fileURLWithPath:[[Utils sharedInstance] pathForResource:file]]; + DebugNSLog(@"Sound file:%@", [fileUrl description]); + + NSSound* sound = [[NSSound alloc] initWithContentsOfURL:fileUrl byReference:YES]; + [self playSound:sound onComplete:callback]; +} + +- (void) playSystem:(NSString*)name onComplete:(WebScriptObject*)callback { + NSSound *systemSound = [NSSound soundNamed:name]; + [self playSound:systemSound onComplete:callback]; +} + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return [self webScriptNameForSelector:selector] == nil; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return YES; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(play:onComplete:)) { + result = @"play"; + } + else if (selector == @selector(playSystem:onComplete:)) { + result = @"playSystem"; + } + + return result; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.h new file mode 100644 index 000000000..269191b39 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.h @@ -0,0 +1,43 @@ +// +// UserDefaults.h +// MacGap +// +// Created by Jeff Hanbury on 16/04/2014. +// Copyright (c) 2014 Twitter. All rights reserved. +// + +#import + +#import "WindowController.h" + +@interface UserDefaults : NSObject + +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (NSString*) getMyDefaults; +- (NSDictionary*) myDefaultsDictionary; +- (void) removeObjectForKey:(NSString*)key; +- (NSArray*) getUserDefaultsKeys; + +- (NSString*) addPrefix:(NSString*)key; + +- (void) setString:(NSString*)key withValue:(NSString*)value; +- (NSString*) getString:(NSString*)key; + +- (void) setInteger:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getInteger:(NSString*)key; + +- (void) setBool:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getBool:(NSString*)key; + +- (void) setFloat:(NSString*)key withValue:(NSString*)value; +- (NSNumber*) getFloat:(NSString*)key; + +// Could also be implemented: +//– setObject:forKey: +//– setDouble:forKey: +//– setURL:forKey: + +@end + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.m new file mode 100644 index 000000000..485687108 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/UserDefaults.m @@ -0,0 +1,211 @@ +// +// UserDefaults.m +// MacGap +// +// Created by Jeff Hanbury on 16/04/2014. +// Copyright (c) 2014 Twitter. All rights reserved. +// + +#import "UserDefaults.h" +#import "JSEventHelper.h" + +@interface UserDefaults() { + +} + +-(void) setupNotificationCenter; + +@end + + +@implementation UserDefaults + +- (id) initWithWebView:(WebView *) view{ + self = [super init]; + + if (self) { + self.webView = view; + [self setupNotificationCenter]; + } + + return self; +} + + +-(void) setupNotificationCenter{ + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(defaultsChanged:) + name:NSUserDefaultsDidChangeNotification + object:nil]; +} + +- (void)defaultsChanged:(NSNotification *)notification { + NSDictionary* returnDict = [self myDefaultsDictionary]; + [JSEventHelper triggerEvent:@"userDefaultsChanged" withArgs:returnDict forWebView:self.webView]; +} + +- (NSString*) getMyDefaults { + NSDictionary* myDefaults = [self myDefaultsDictionary]; + + return [[Utils sharedInstance] convertDictionaryToJSON:myDefaults]; +} + +- (NSDictionary*) myDefaultsDictionary { + NSString* prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; + NSMutableDictionary* returnDict = [[NSMutableDictionary alloc] init]; + + // Get the user defaults. + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + // Build up a dictionary containing just the items beginning with our + // prefix. + for (NSString* key in [self getUserDefaultsKeys]) { + if ([key hasPrefix:prefix]) { + id val = [defaults valueForKey:key]; + [returnDict setObject:val forKey:key]; + } + } + + return returnDict; +} + +- (NSArray*) getUserDefaultsKeys { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [[prefs dictionaryRepresentation] allKeys]; +} + +- (void) removeObjectForKey:(NSString*)key { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:prefixedKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + +// Check we have a standard prefix for JS-modified keys, for security purposes. +// If not, add it. This stops JavaScript from ever being able to modify keys +// it did not create. +- (NSString*) addPrefix:(NSString*)key { + NSString* prefix; + prefix = [kWebScriptNamespace stringByAppendingString:@"_"]; + + if (![key hasPrefix:prefix]) { + key = [prefix stringByAppendingString:key]; + } + return key; +} + +// String + +- (void) setString:(NSString*)key withValue:(NSString*)value { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + [prefs setObject:value forKey:prefixedKey]; +} + +- (NSString*) getString:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [prefs stringForKey:key]; +} + +// All the following must convert their type to NSNumber for JavaScript. + +// Integer + +- (void) setInteger:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + NSInteger myInt = [value intValue]; + [prefs setInteger:myInt forKey:prefixedKey]; +} + +- (NSNumber*) getInteger:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithInteger:[prefs integerForKey:key]]; +} + +// Boolean + +- (void) setBool:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + BOOL myBool = [value boolValue]; + [prefs setBool:myBool forKey:prefixedKey]; +} + +- (NSNumber*) getBool:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithBool:[prefs boolForKey:key]]; +} + +// Float + +- (void) setFloat:(NSString*)key withValue:(NSString*)value { + NSString* prefixedKey; + prefixedKey = [self addPrefix:key]; + + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + float myFloat = [value floatValue]; + [prefs setFloat:myFloat forKey:prefixedKey]; +} + +- (NSNumber*) getFloat:(NSString *)key { + NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults]; + return [NSNumber numberWithFloat:[prefs floatForKey:key]]; +} + + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(getMyDefaults)) { + result = @"getMyDefaults"; + } + + if (selector == @selector(removeObjectForKey:)) { + result = @"removeObjectForKey"; + } + + else if (selector == @selector(setString:withValue:)) { + result = @"setString"; + } else if (selector == @selector(getString:)) { + result = @"getString"; + } + + else if (selector == @selector(setInteger:withValue:)) { + result = @"setInteger"; + } else if (selector == @selector(getInteger:)) { + result = @"getInteger"; + } + + else if (selector == @selector(setBool:withValue:)) { + result = @"setBool"; + } else if (selector == @selector(getBool:)) { + result = @"getBool"; + } + + else if (selector == @selector(setFloat:withValue:)) { + result = @"setFloat"; + } else if (selector == @selector(getFloat:)) { + result = @"getFloat"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.h new file mode 100644 index 000000000..62c7b7e83 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.h @@ -0,0 +1,9 @@ +@interface Fonts : NSObject { +} + +- (NSArray*) availableFonts; +- (NSArray*) availableFontFamilies; +- (NSArray*) availableMembersOfFontFamily:(NSString*)fontFamily; +- (CGFloat) defaultLineHeightForFont:(NSString *)theFontName ofSize:(CGFloat)theFontSize; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.m new file mode 100644 index 000000000..b17818a53 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Commands/fonts.m @@ -0,0 +1,48 @@ +#import "fonts.h" + +@implementation Fonts + + +- (NSArray*) availableFonts { + return [[NSFontManager sharedFontManager] availableFonts]; +} + +- (NSArray*) availableFontFamilies { + return [[NSFontManager sharedFontManager] availableFontFamilies]; +} + +- (NSArray*) availableMembersOfFontFamily:(NSString *)fontFamily { + return [[NSFontManager sharedFontManager] availableMembersOfFontFamily:fontFamily]; +} + +- (CGFloat) defaultLineHeightForFont:(NSString*)theFontName ofSize:(CGFloat)theFontSize { + NSFont *theFont = [NSFont fontWithName:theFontName size:theFontSize]; + NSLayoutManager *lm = [[NSLayoutManager alloc] init]; + + return [lm defaultLineHeightForFont:theFont]; +} + + +#pragma mark WebScripting Protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector { + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector { + id result = nil; + + if (selector == @selector(availableMembersOfFontFamily:)) { + result = @"availableMembersOfFontFamily"; + } else if (selector == @selector(defaultLineHeightForFont:ofSize:)) { + result = @"defaultLineHeightForFont"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name { + return NO; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Constants.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Constants.h new file mode 100644 index 000000000..1fe59d6cc --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Constants.h @@ -0,0 +1,7 @@ +// Application constants + +#define kStartPage @"http://127.0.0.1:9993/" + +#define kStartFolder @"." + +#define kWebScriptNamespace @"macgap" \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.h new file mode 100644 index 000000000..65890a5ee --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.h @@ -0,0 +1,15 @@ +#import +#import + +@class WebViewDelegate; + +@interface ContentView : NSView { + IBOutlet WebView* webView; + WebViewDelegate* delegate; +} + +@property (retain) WebView* webView; +@property (retain) WebViewDelegate* delegate; +@property (strong) IBOutlet NSMenu *mainMenu; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.m new file mode 100644 index 000000000..24e58cd1c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/ContentView.m @@ -0,0 +1,68 @@ +#import "ContentView.h" +#import "WebViewDelegate.h" +#import "AppDelegate.h" +#import "JSEventHelper.h" + +@interface WebPreferences (WebPreferencesPrivate) + - (void)_setLocalStorageDatabasePath:(NSString *)path; + - (void) setLocalStorageEnabled: (BOOL) localStorageEnabled; + - (void) setDatabasesEnabled:(BOOL)databasesEnabled; + - (void) setDeveloperExtrasEnabled:(BOOL)developerExtrasEnabled; + - (void) setWebGLEnabled:(BOOL)webGLEnabled; + - (void) setOfflineWebApplicationCacheEnabled:(BOOL)offlineWebApplicationCacheEnabled; +@end + +@implementation ContentView + +@synthesize webView, delegate, mainMenu; + +- (void) awakeFromNib +{ + WebPreferences *webPrefs = [WebPreferences standardPreferences]; + + NSString *cappBundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; + NSString *applicationSupportFile = [@"~/Library/Application Support/" stringByExpandingTildeInPath]; + NSString *savePath = [NSString pathWithComponents:[NSArray arrayWithObjects:applicationSupportFile, cappBundleName, @"LocalStorage", nil]]; + [webPrefs _setLocalStorageDatabasePath:savePath]; + [webPrefs setLocalStorageEnabled:YES]; + [webPrefs setDatabasesEnabled:YES]; + [webPrefs setDeveloperExtrasEnabled:[[NSUserDefaults standardUserDefaults] boolForKey: @"developer"]]; + [webPrefs setOfflineWebApplicationCacheEnabled:YES]; + [webPrefs setWebGLEnabled:YES]; + + [self.webView setPreferences:webPrefs]; + + NSHTTPCookieStorage *cookieStorage = [NSHTTPCookieStorage + sharedHTTPCookieStorage]; + [cookieStorage setCookieAcceptPolicy:NSHTTPCookieAcceptPolicyAlways]; + + [self.webView setApplicationNameForUserAgent: @"MacGap"]; + + self.delegate = [[WebViewDelegate alloc] initWithMenu:[NSApp mainMenu]]; + [self.webView setFrameLoadDelegate:self.delegate]; + [self.webView setUIDelegate:self.delegate]; + [self.webView setResourceLoadDelegate:self.delegate]; + [self.webView setDownloadDelegate:self.delegate]; + [self.webView setPolicyDelegate:self.delegate]; + [self.webView setDrawsBackground:NO]; + [self.webView setShouldCloseWithWindow:NO]; + + [self.webView setGroupName:@"MacGap"]; + +} + +- (void) windowResized:(NSNotification*)notification; +{ + NSWindow* window = (NSWindow*)notification.object; + NSSize size = [window frame].size; + + DebugNSLog(@"window width = %f, window height = %f", size.width, size.height); + + bool isFullScreen = (window.styleMask & NSFullScreenWindowMask) == NSFullScreenWindowMask; + int titleBarHeight = isFullScreen ? 0 : [[Utils sharedInstance] titleBarHeight:window]; + + [self.webView setFrame:NSMakeRect(0, 0, size.width, size.height - titleBarHeight)]; + [JSEventHelper triggerEvent:@"orientationchange" forWebView:self.webView]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.h new file mode 100644 index 000000000..401f3e396 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.h @@ -0,0 +1,20 @@ +// +// Helper.h +// MacGap +// +// Created by Liam Kaufman Simpkins on 12-01-22. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import +#import "WindowController.h" + +@interface JSEventHelper : NSObject + ++ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView; ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.m new file mode 100644 index 000000000..65406b3c0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/JSEventHelper.m @@ -0,0 +1,41 @@ +// +// Helper.m +// MacGap +// +// Created by Liam Kaufman Simpkins on 12-01-22. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import "JSEventHelper.h" + +@implementation JSEventHelper + ++ (void) triggerEvent:(NSString *)event forWebView:(WebView *)webView { + [self triggerEvent:event withArgs:[NSMutableDictionary dictionary] forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forWebView:(WebView *)webView { + [self triggerEvent:event withArgs:args forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event withArgs:(NSDictionary *)args forObject:(NSString *)objName forWebView:(WebView *)webView { + + // Convert args Dictionary to JSON. + NSString* jsonString = [[Utils sharedInstance] convertDictionaryToJSON:args]; + + // Create the event JavaScript and run it. + NSString * str = [NSString stringWithFormat:@"var e = document.createEvent('Events'); e.initEvent('%@', true, false); e.data=%@; %@.dispatchEvent(e); ", event, jsonString, objName]; + [webView stringByEvaluatingJavaScriptFromString:str]; +} + ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forWebView:(WebView *)webView { + [self triggerEvent:event forDetail:detail forObject:@"document" forWebView:webView]; +} + ++ (void) triggerEvent:(NSString *)event forDetail:(NSString *)detail forObject:(NSString *)objName forWebView:(WebView *)webView { + NSString *detailEscaped = [detail stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]; + NSString *str = [NSString stringWithFormat:@"var e = new CustomEvent('%@', { 'detail': decodeURIComponent(\"%@\") }); %@.dispatchEvent(e); ", event, detailEscaped, objName]; + [webView stringByEvaluatingJavaScriptFromString:str]; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.h new file mode 100644 index 000000000..f573d881a --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.h @@ -0,0 +1,20 @@ +#import +#import + +#define DEG_EPS 0.001 +#define fequal(a,b) (fabs((a) - (b)) < DEG_EPS) +#define fequalzero(a) (fabs(a) < DEG_EPS) + +@class LoadingView; + +@interface Utils : NSObject { +} + +- (float) titleBarHeight:(NSWindow*)aWindow; +- (NSString*) pathForResource:(NSString*)resourcepath; +- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict; +- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray; + ++ (Utils*) sharedInstance; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.m new file mode 100644 index 000000000..8d85c2949 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Utils.m @@ -0,0 +1,93 @@ +#import "Utils.h" +#import + +static Utils* sharedInstance = nil; + +@implementation Utils + +- (float) titleBarHeight:(NSWindow*)aWindow +{ + NSRect frame = [aWindow frame]; + NSRect contentRect = [NSWindow contentRectForFrameRect: frame + styleMask: NSTitledWindowMask]; + + return (frame.size.height - contentRect.size.height); +} + +- (NSString*) pathForResource:(NSString*)resourcepath +{ + NSBundle * mainBundle = [NSBundle mainBundle]; + NSMutableArray *directoryParts = [NSMutableArray arrayWithArray:[resourcepath componentsSeparatedByString:@"/"]]; + NSString *filename = [directoryParts lastObject]; + [directoryParts removeLastObject]; + + NSString *directoryStr = [NSString stringWithFormat:@"%@/%@", kStartFolder, [directoryParts componentsJoinedByString:@"/"]]; + return [mainBundle pathForResource:filename + ofType:@"" + inDirectory:directoryStr]; +} + +- (NSString*) convertDictionaryToJSON:(NSDictionary*)dict { + // Convert defaults Dictionary to JSON. + NSError *error; + NSData *jsonData = [NSJSONSerialization + dataWithJSONObject:dict + options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about the readability of the generated string + error:&error]; + + NSString *jsonString; + if (! jsonData) { + NSLog(@"Got an error converting to JSON: %@", error); + } + else { + jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; + } + + return jsonString; +} + +// Convert JavaScript array (arrives as a WebScriptObject) into an NSArray of strings. +- (NSArray*) convertJSarrayToNSArray:(WebScriptObject*)jsArray { + NSInteger count = [[jsArray valueForKey:@"length"] integerValue]; + + NSMutableArray *args = [NSMutableArray array]; + for (int i = 0; i < count; i++) { + NSString *item = [jsArray webScriptValueAtIndex:i]; + if ([item isKindOfClass:[NSString class]]) { + [args addObject:item]; + } + } + + return args; +} + +#pragma mark - +#pragma mark Singleton methods + ++ (Utils*) sharedInstance +{ + @synchronized(self) + { + if (sharedInstance == nil){ + sharedInstance = [[Utils alloc] init]; + } + } + return sharedInstance; +} + ++ (id) allocWithZone:(NSZone *)zone { + @synchronized(self) { + if (sharedInstance == nil) { + sharedInstance = [super allocWithZone:zone]; + return sharedInstance; // assignment and return on first allocation + } + } + return nil; // on subsequent allocation attempts return nil +} + +- (id) copyWithZone:(NSZone *)zone +{ + return self; +} + +@end \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.h new file mode 100644 index 000000000..49c6da6b9 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.h @@ -0,0 +1,49 @@ +#import +#import + +@class Sound; +@class Dock; +@class Growl; +@class Notice; +@class Path; +@class App; +@class Window; +@class Clipboard; +@class Fonts; +@class MenuProxy; +@class UserDefaults; + +@class WindowController; + +@interface WebViewDelegate : NSObject { + Sound* sound; + Dock* dock; + Growl* growl; + Notice* notice; + Path* path; + App* app; + Window* window; + Clipboard* clipboard; + Fonts* fonts; + NSMenu *mainMenu; + UserDefaults* userDefaults; +} + + + +@property (nonatomic, retain) Sound* sound; +@property (nonatomic, retain) Dock* dock; +@property (nonatomic, retain) Growl* growl; +@property (nonatomic, retain) Notice* notice; +@property (nonatomic, retain) Path* path; +@property (nonatomic, retain) App* app; +@property (nonatomic, retain) Window* window; +@property (nonatomic, retain) Clipboard* clipboard; +@property (nonatomic, retain) Fonts* fonts; +@property (nonatomic, retain) MenuProxy* menu; +@property (nonatomic, retain) UserDefaults* userDefaults; + +@property (nonatomic, retain) WindowController *requestedWindow; + +- (id) initWithMenu:(NSMenu*)menu; +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.m new file mode 100644 index 000000000..505780183 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/WebViewDelegate.m @@ -0,0 +1,206 @@ +#import "WebViewDelegate.h" +#import "Sound.h" +#import "Dock.h" +#import "Notice.h" +#import "Path.h" +#import "App.h" +#import "Window.h" +#import "WindowController.h" +#import "Clipboard.h" +#import "Fonts.h" +#import "MenuProxy.h" +#import "UserDefaults.h" + +@implementation WebViewDelegate + +@synthesize sound; +@synthesize dock; +@synthesize growl; +@synthesize notice; +@synthesize path; +@synthesize app; +@synthesize window; +@synthesize requestedWindow; +@synthesize clipboard; +@synthesize fonts; +@synthesize menu; +@synthesize userDefaults; + +- (id) initWithMenu:(NSMenu*)aMenu +{ + self = [super init]; + if (!self) + return nil; + + mainMenu = aMenu; + return self; +} + +- (void) webView:(WebView*)webView didClearWindowObject:(WebScriptObject*)windowScriptObject forFrame:(WebFrame *)frame +{ + JSContextRef context = [frame globalContext]; + if (self.sound == nil) { self.sound = [[Sound alloc] initWithContext:context]; } + if (self.dock == nil) { self.dock = [Dock new]; } + if (self.path == nil) { self.path = [Path new]; } + if (self.clipboard == nil) { self.clipboard = [Clipboard new]; } + if (self.fonts == nil) { self.fonts = [Fonts new]; } + + if (self.notice == nil && [Notice available] == YES) { + self.notice = [[Notice alloc] initWithWebView:webView]; + } + + if (self.app == nil) { + self.app = [[App alloc] initWithWebView:webView]; + } + + if (self.window == nil) { + self.window = [[Window alloc] initWithWebView:webView]; + } + + if (self.menu == nil) { + self.menu = [MenuProxy proxyWithContext:context andMenu:mainMenu]; + } + + if (self.userDefaults == nil) { + self.userDefaults = [[UserDefaults alloc] initWithWebView:webView]; + } + + [windowScriptObject setValue:self forKey:kWebScriptNamespace]; +} + + +- (void)webView:(WebView *)sender runOpenPanelForFileButtonWithResultListener:(id < WebOpenPanelResultListener >)resultListener allowMultipleFiles:(BOOL)allowMultipleFiles{ + + NSOpenPanel * openDlg = [NSOpenPanel openPanel]; + + [openDlg setCanChooseFiles:YES]; + [openDlg setCanChooseDirectories:NO]; + + [openDlg beginWithCompletionHandler:^(NSInteger result){ + if (result == NSFileHandlingPanelOKButton) { + NSArray * files = [[openDlg URLs] valueForKey: @"relativePath"]; + [resultListener chooseFilenames: files]; + } else { + [resultListener cancel]; + } + }]; +} + +- (void) webView:(WebView*)webView addMessageToConsole:(NSDictionary*)message +{ + if (![message isKindOfClass:[NSDictionary class]]) { + return; + } + + NSLog(@"JavaScript console: %@:%@: %@", + [[message objectForKey:@"sourceURL"] lastPathComponent], // could be nil + [message objectForKey:@"lineNumber"], + [message objectForKey:@"message"]); +} + +- (void)webView:(WebView *)sender runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:@"OK"]; + [alert setMessageText:message]; + [alert setAlertStyle:NSWarningAlertStyle]; + [alert runModal]; +} + +- (BOOL)webView:(WebView *)sender runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WebFrame *)frame +{ + NSAlert *alert = [[NSAlert alloc] init]; + [alert addButtonWithTitle:@"Yes"]; + [alert addButtonWithTitle:@"No"]; + [alert setMessageText:message]; + [alert setAlertStyle:NSWarningAlertStyle]; + + if ([alert runModal] == NSAlertFirstButtonReturn) + return YES; + else + return NO; +} + +/* + By default the size of a database is set to 0 [1]. When a database is being created + it calls this delegate method to get an increase in quota size - or call an error. + PS this method is defined in WebUIDelegatePrivate and may make it difficult, but + not impossible [2], to get an app accepted into the mac app store. + + Further reading: + [1] http://stackoverflow.com/questions/353808/implementing-a-webview-database-quota-delegate + [2] http://stackoverflow.com/questions/4527905/how-do-i-enable-local-storage-in-my-webkit-based-application/4608549#4608549 + */ +- (void)webView:(WebView *)sender frame:(WebFrame *)frame exceededDatabaseQuotaForSecurityOrigin:(id) origin database:(NSString *)databaseIdentifier +{ + static const unsigned long long defaultQuota = 5 * 1024 * 1024; + if ([origin respondsToSelector: @selector(setQuota:)]) { + [origin performSelector:@selector(setQuota:) withObject:[NSNumber numberWithLongLong: defaultQuota]]; + } else { + NSLog(@"could not increase quota for %lld", defaultQuota); + } +} + +- (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems +{ + NSMutableArray *webViewMenuItems = [defaultMenuItems mutableCopy]; + + if (webViewMenuItems) + { + NSEnumerator *itemEnumerator = [defaultMenuItems objectEnumerator]; + NSMenuItem *menuItem = nil; + while ((menuItem = [itemEnumerator nextObject])) + { + NSInteger tag = [menuItem tag]; + + switch (tag) + { + case WebMenuItemTagOpenLinkInNewWindow: + case WebMenuItemTagDownloadLinkToDisk: + case WebMenuItemTagCopyLinkToClipboard: + case WebMenuItemTagOpenImageInNewWindow: + case WebMenuItemTagDownloadImageToDisk: + case WebMenuItemTagCopyImageToClipboard: + case WebMenuItemTagOpenFrameInNewWindow: + case WebMenuItemTagGoBack: + case WebMenuItemTagGoForward: + case WebMenuItemTagStop: + case WebMenuItemTagOpenWithDefaultApplication: + case WebMenuItemTagReload: + [webViewMenuItems removeObjectIdenticalTo: menuItem]; + } + } + } + + return webViewMenuItems; +} + +- (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request{ + requestedWindow = [[WindowController alloc] initWithRequest:request]; + return requestedWindow.contentView.webView; +} + +- (void)webViewShow:(WebView *)sender{ + [requestedWindow showWindow:sender]; +} + +- (void)webView:(WebView *)webView decidePolicyForNewWindowAction:(NSDictionary *)actionInformation request:(NSURLRequest *)request newFrameName:(NSString *)frameName decisionListener:(id < WebPolicyDecisionListener >)listener +{ + [[NSWorkspace sharedWorkspace] openURL:[request URL]]; + [listener ignore]; +} + +#pragma mark WebScripting protocol + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return YES; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return NO; +} + + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.h b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.h new file mode 100644 index 000000000..f721376e0 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.h @@ -0,0 +1,23 @@ +#import + +#import "WindowController.h" + +@interface Window : NSObject{ + CGRect _oldRestoreFrame; +} + +@property (retain, nonatomic) WindowController *windowController; +@property (nonatomic, retain) WebView *webView; + +- (id) initWithWebView:(WebView *)view; +- (void) open:(NSDictionary *)properties; +- (void) move:(NSDictionary *)properties; +- (void) resize:(NSDictionary *) properties; +- (Boolean) isMaximized; +- (CGFloat) getX; +- (CGFloat) getY; +- (void) maximize; +- (void) restore; +- (void) toggleFullscreen; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.m b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.m new file mode 100644 index 000000000..2444f62ea --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Classes/Window.m @@ -0,0 +1,94 @@ +#import "Window.h" + +@implementation Window + +@synthesize windowController, webView; + +- (id) initWithWebView:(WebView*)view +{ + if(self = [super init]) { + self.webView = view; + } + return self; +} + +- (void) open:(NSDictionary *)properties +{ + self.windowController = [[WindowController alloc] initWithURL:[properties valueForKey:@"url"]]; + [self.windowController showWindow: [NSApplication sharedApplication].delegate]; + [self.windowController.window makeKeyWindow]; +} + +- (void) minimize { + [[NSApp mainWindow] miniaturize:[NSApp mainWindow]]; +} + +- (void) toggleFullscreen { + [[NSApp mainWindow] toggleFullScreen:[NSApp mainWindow]]; +} + +- (void) maximize { + CGRect a = [NSApp mainWindow].frame; + _oldRestoreFrame = CGRectMake(a.origin.x, a.origin.y, a.size.width, a.size.height); + [[NSApp mainWindow] setFrame:[[NSScreen mainScreen] visibleFrame] display:YES]; +} + +- (Boolean) isMaximized { + NSRect a = [NSApp mainWindow].frame; + NSRect b = [[NSScreen mainScreen] visibleFrame]; + return a.origin.x == b.origin.x && a.origin.y == b.origin.y && a.size.width == b.size.width && a.size.height == b.size.height; +} + +- (CGFloat) getX { + NSRect frame = [self.webView window].frame; + return frame.origin.x; +} + +- (CGFloat) getY { + NSRect frame = [self.webView window].frame; + return frame.origin.y; +} + +- (void) move:(NSDictionary *)properties +{ + NSRect frame = [self.webView window].frame; + frame.origin.x = [[properties valueForKey:@"x"] doubleValue]; + frame.origin.y = [[properties valueForKey:@"y"] doubleValue]; + [[self.webView window] setFrame:frame display:YES]; + +} + +- (void) resize:(NSDictionary *) properties +{ + NSRect frame = [self.webView window].frame; + frame.size.width = [[properties valueForKey:@"width"] doubleValue]; + frame.size.height = [[properties valueForKey:@"height"] doubleValue]; + [[self.webView window] setFrame:frame display:YES]; +} + + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector{ + id result = nil; + + if (selector == @selector(open:)) { + result = @"open"; + }else if (selector == @selector(move:)){ + result = @"move"; + }else if (selector == @selector(resize:)){ + result = @"resize"; + } + + return result; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.h b/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.h new file mode 100644 index 000000000..6c1a2f513 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.h @@ -0,0 +1,10 @@ +#import + +@interface Clipboard : NSObject { + +} + +- (void) copy:(NSString*)text; +- (NSString *) paste; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.m b/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.m new file mode 100644 index 000000000..1c18dea38 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/Clipboard.m @@ -0,0 +1,51 @@ +// +// clipboard.m +// MacGap +// +// Created by David Zorychta on 2013-07-22. +// Copyright (c) 2013 Twitter. All rights reserved. +// + +#import "Clipboard.h" + +@implementation Clipboard + +- (void) copy:(NSString*)text { + [[NSPasteboard generalPasteboard] clearContents]; + [[NSPasteboard generalPasteboard] setString:text forType:NSStringPboardType]; +} + +- (NSString *) paste { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSArray *classArray = [NSArray arrayWithObject:[NSString class]]; + NSDictionary *options = [NSDictionary dictionary]; + BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; + if (ok) { + NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; + return (NSString *) [objectsToPaste objectAtIndex:0]; + } + return @""; +} + ++ (NSString*) webScriptNameForSelector:(SEL)selector +{ + id result = nil; + + if (selector == @selector(copy:)) { + result = @"copy"; + } + + return result; +} + ++ (BOOL) isSelectorExcludedFromWebScript:(SEL)selector +{ + return NO; +} + ++ (BOOL) isKeyExcludedFromWebScript:(const char*)name +{ + return YES; +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Info.plist b/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Info.plist new file mode 100644 index 000000000..2031cefcc --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Info.plist @@ -0,0 +1,34 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + ZeroTier One + CFBundleIconFile + application.icns + CFBundleIdentifier + com.zerotier.$(PRODUCT_NAME:rfc1034identifier) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ZeroTier One + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.utilities + LSMinimumSystemVersion + ${MACOSX_DEPLOYMENT_TARGET} + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Prefix.pch b/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Prefix.pch new file mode 100644 index 000000000..ad05e8420 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/MacGap-Prefix.pch @@ -0,0 +1,15 @@ +// +// Prefix header for all source files of the 'MacGap' target in the 'MacGap' project +// + +#ifdef __OBJC__ + #ifdef _DEBUG + #define DebugNSLog(format, ...) NSLog(format, ## __VA_ARGS__) + #else + #define DebugNSLog(format, ...) + #endif + + #import + #import "Constants.h" + #import "Utils.h" +#endif diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.h b/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.h new file mode 100644 index 000000000..72927effa --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.h @@ -0,0 +1,13 @@ +#import +#import "ContentView.h" + +@interface WindowController : NSWindowController { + +} + +- (id) initWithURL:(NSString *) url; +- (id) initWithRequest: (NSURLRequest *)request; +@property (retain) NSURL * url; +@property (retain) IBOutlet ContentView *contentView; + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.m b/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.m new file mode 100644 index 000000000..2765a2e3c --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/WindowController.m @@ -0,0 +1,54 @@ +#import "WindowController.h" + + +@interface WindowController() { + +} + +-(void) notificationCenter; + +@end + +@implementation WindowController + +@synthesize contentView, url; + +- (id) initWithURL:(NSString *) relativeURL{ + self = [super initWithWindowNibName:@"Window"]; + self.url = [NSURL URLWithString:relativeURL relativeToURL:[[NSBundle mainBundle] resourceURL]]; + + [self.window setFrameAutosaveName:@"MacGapWindow"]; + [self notificationCenter]; + + return self; +} + +-(id) initWithRequest: (NSURLRequest *)request{ + self = [super initWithWindowNibName:@"Window"]; + [self notificationCenter]; + [[self.contentView.webView mainFrame] loadRequest:request]; + + return self; +} + +-(void) notificationCenter{ + [[NSNotificationCenter defaultCenter] addObserver:self.contentView + selector:@selector(windowResized:) + name:NSWindowDidResizeNotification + object:[self window]]; +} + +- (void)windowDidLoad +{ + [super windowDidLoad]; + + if (self.url != nil) { + [self.contentView.webView setMainFrameURL:[self.url absoluteString]]; + } + + + // Implement this method to handle any initialization after your + // window controller's window has been loaded from its nib file. +} + +@end diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Credits.rtf b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Credits.rtf new file mode 100644 index 000000000..6f388f662 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Credits.rtf @@ -0,0 +1,13 @@ +{\rtf1\ansi\ansicpg1252\cocoartf1347\cocoasubrtf570 +{\fonttbl\f0\fswiss\fcharset0 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\vieww9600\viewh8400\viewkind0 +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 + +\f0\b\fs24 \cf0 (c)2011-2015 ZeroTier, Inc.\ +Licensed under the GNU GPLv3\ +\ +UI Wrapper MacGap (c) Twitter, Inc.\ +Licensed under the MIT License\ +http://macgap.com/\ +} \ No newline at end of file diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/InfoPlist.strings b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/InfoPlist.strings new file mode 100644 index 000000000..477b28ff8 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/InfoPlist.strings @@ -0,0 +1,2 @@ +/* Localized versions of Info.plist keys */ + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/MainMenu.xib b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/MainMenu.xib new file mode 100644 index 000000000..998c505a8 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/MainMenu.xib @@ -0,0 +1,3404 @@ + + + + 1080 + 14D136 + 7702 + 1347.57 + 758.70 + + com.apple.InterfaceBuilder.CocoaPlugin + 7702 + + + NSCustomObject + NSMenu + NSMenuItem + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + NSApplication + + + FirstResponder + + + NSApplication + + + AppDelegate + + + AMainMenu + + + + ZeroTier One + + 1048576 + 2147483647 + + NSImage + NSMenuCheckmark + + + NSImage + NSMenuMixedState + + submenuAction: + + + ZeroTier One + + + + About ZeroTier One + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Preferences… + , + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Services + + 1048576 + 2147483647 + + + submenuAction: + + + Services + + _NSServicesMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Hide MacGap + h + 1048576 + 2147483647 + + + + + + Hide Others + h + 1572864 + 2147483647 + + + + + + Show All + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Quit ZeroTier One + q + 1048576 + 2147483647 + + + + + _NSAppleMenu + + + + + File + + 1048576 + 2147483647 + + + submenuAction: + + + File + + + + New + n + 1048576 + 2147483647 + + + + + + Open… + o + 1048576 + 2147483647 + + + + + + Open Recent + + 1048576 + 2147483647 + + + submenuAction: + + + Open Recent + + + + Clear Menu + + 1048576 + 2147483647 + + + + + _NSRecentDocumentsMenu + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Close + w + 1048576 + 2147483647 + + + + + + Save… + s + 1048576 + 2147483647 + + + + + + Revert to Saved + + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Page Setup... + P + 1179648 + 2147483647 + + + + + + + Print… + p + 1048576 + 2147483647 + + + + + + + + + Edit + + 1048576 + 2147483647 + + + submenuAction: + + + Edit + + + + Undo + z + 1048576 + 2147483647 + + + + + + Redo + Z + 1179648 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Cut + x + 1048576 + 2147483647 + + + + + + Copy + c + 1048576 + 2147483647 + + + + + + Paste + v + 1048576 + 2147483647 + + + + + + Paste and Match Style + V + 1572864 + 2147483647 + + + + + + Delete + + 1048576 + 2147483647 + + + + + + Select All + a + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Find + + 1048576 + 2147483647 + + + submenuAction: + + + Find + + + + Find… + f + 1048576 + 2147483647 + + + 1 + + + + Find and Replace… + f + 1572864 + 2147483647 + + + 12 + + + + Find Next + g + 1048576 + 2147483647 + + + 2 + + + + Find Previous + G + 1179648 + 2147483647 + + + 3 + + + + Use Selection for Find + e + 1048576 + 2147483647 + + + 7 + + + + Jump to Selection + j + 1048576 + 2147483647 + + + + + + + + + Spelling and Grammar + + 1048576 + 2147483647 + + + submenuAction: + + + Spelling and Grammar + + + + Show Spelling and Grammar + : + 1048576 + 2147483647 + + + + + + Check Document Now + ; + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Check Spelling While Typing + + 1048576 + 2147483647 + + + + + + Check Grammar With Spelling + + 1048576 + 2147483647 + + + + + + Correct Spelling Automatically + + 2147483647 + + + + + + + + + Substitutions + + 1048576 + 2147483647 + + + submenuAction: + + + Substitutions + + + + Show Substitutions + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Smart Copy/Paste + f + 1048576 + 2147483647 + + + 1 + + + + Smart Quotes + g + 1048576 + 2147483647 + + + 2 + + + + Smart Dashes + + 2147483647 + + + + + + Smart Links + G + 1179648 + 2147483647 + + + 3 + + + + Text Replacement + + 2147483647 + + + + + + + + + Transformations + + 2147483647 + + + submenuAction: + + + Transformations + + + + Make Upper Case + + 2147483647 + + + + + + Make Lower Case + + 2147483647 + + + + + + Capitalize + + 2147483647 + + + + + + + + + Speech + + 1048576 + 2147483647 + + + submenuAction: + + + Speech + + + + Start Speaking + + 1048576 + 2147483647 + + + + + + Stop Speaking + + 1048576 + 2147483647 + + + + + + + + + + + + Format + + 2147483647 + + + submenuAction: + + + Format + + + + Font + + 2147483647 + + + submenuAction: + + + Font + + + + Show Fonts + t + 1048576 + 2147483647 + + + + + + Bold + b + 1048576 + 2147483647 + + + 2 + + + + Italic + i + 1048576 + 2147483647 + + + 1 + + + + Underline + u + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Bigger + + + 1048576 + 2147483647 + + + 3 + + + + Smaller + - + 1048576 + 2147483647 + + + 4 + + + + YES + YES + + + 2147483647 + + + + + + Kern + + 2147483647 + + + submenuAction: + + + Kern + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Tighten + + 2147483647 + + + + + + Loosen + + 2147483647 + + + + + + + + + Ligature + + 2147483647 + + + submenuAction: + + + Ligature + + + + Use Default + + 2147483647 + + + + + + Use None + + 2147483647 + + + + + + Use All + + 2147483647 + + + + + + + + + Baseline + + 2147483647 + + + submenuAction: + + + Baseline + + + + Use Default + + 2147483647 + + + + + + Superscript + + 2147483647 + + + + + + Subscript + + 2147483647 + + + + + + Raise + + 2147483647 + + + + + + Lower + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Colors + C + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Copy Style + c + 1572864 + 2147483647 + + + + + + Paste Style + v + 1572864 + 2147483647 + + + + + _NSFontMenu + + + + + Text + + 2147483647 + + + submenuAction: + + + Text + + + + Align Left + { + 1048576 + 2147483647 + + + + + + Center + | + 1048576 + 2147483647 + + + + + + Justify + + 2147483647 + + + + + + Align Right + } + 1048576 + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + Writing Direction + + 2147483647 + + + submenuAction: + + + Writing Direction + + + + YES + Paragraph + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + YES + YES + + + 2147483647 + + + + + + YES + Selection + + 2147483647 + + + + + + CURlZmF1bHQ + + 2147483647 + + + + + + CUxlZnQgdG8gUmlnaHQ + + 2147483647 + + + + + + CVJpZ2h0IHRvIExlZnQ + + 2147483647 + + + + + + + + + YES + YES + + + 2147483647 + + + + + + Show Ruler + + 2147483647 + + + + + + Copy Ruler + c + 1310720 + 2147483647 + + + + + + Paste Ruler + v + 1310720 + 2147483647 + + + + + + + + + + + + View + + 1048576 + 2147483647 + + + submenuAction: + + + View + + + + Show Toolbar + t + 1572864 + 2147483647 + + + + + + Customize Toolbar… + + 1048576 + 2147483647 + + + + + + + + + Window + + 1048576 + 2147483647 + + + submenuAction: + + + Window + + + + Minimize + m + 1048576 + 2147483647 + + + + + + Zoom + + 1048576 + 2147483647 + + + + + + YES + YES + + + 1048576 + 2147483647 + + + + + + Bring All to Front + + 1048576 + 2147483647 + + + + + _NSWindowsMenu + + + + + Help + + 2147483647 + + + submenuAction: + + + Help + + + + ZeroTier One Help + ? + 1048576 + 2147483647 + + + + + _NSHelpMenu + + + + _NSMainMenu + + + + + + + terminate: + + + + 449 + + + + orderFrontStandardAboutPanel: + + + + 142 + + + + delegate + + + + 547 + + + + performMiniaturize: + + + + 37 + + + + arrangeInFront: + + + + 39 + + + + print: + + + + 86 + + + + runPageLayout: + + + + 87 + + + + clearRecentDocuments: + + + + 127 + + + + performClose: + + + + 193 + + + + toggleContinuousSpellChecking: + + + + 222 + + + + undo: + + + + 223 + + + + copy: + + + + 224 + + + + checkSpelling: + + + + 225 + + + + paste: + + + + 226 + + + + stopSpeaking: + + + + 227 + + + + cut: + + + + 228 + + + + showGuessPanel: + + + + 230 + + + + redo: + + + + 231 + + + + selectAll: + + + + 232 + + + + startSpeaking: + + + + 233 + + + + delete: + + + + 235 + + + + performZoom: + + + + 240 + + + + performFindPanelAction: + + + + 241 + + + + centerSelectionInVisibleArea: + + + + 245 + + + + toggleGrammarChecking: + + + + 347 + + + + toggleSmartInsertDelete: + + + + 355 + + + + toggleAutomaticQuoteSubstitution: + + + + 356 + + + + toggleAutomaticLinkDetection: + + + + 357 + + + + saveDocument: + + + + 362 + + + + revertDocumentToSaved: + + + + 364 + + + + runToolbarCustomizationPalette: + + + + 365 + + + + toggleToolbarShown: + + + + 366 + + + + hide: + + + + 367 + + + + hideOtherApplications: + + + + 368 + + + + unhideAllApplications: + + + + 370 + + + + newDocument: + + + + 373 + + + + openDocument: + + + + 374 + + + + raiseBaseline: + + + + 426 + + + + lowerBaseline: + + + + 427 + + + + copyFont: + + + + 428 + + + + subscript: + + + + 429 + + + + superscript: + + + + 430 + + + + tightenKerning: + + + + 431 + + + + underline: + + + + 432 + + + + orderFrontColorPanel: + + + + 433 + + + + useAllLigatures: + + + + 434 + + + + loosenKerning: + + + + 435 + + + + pasteFont: + + + + 436 + + + + unscript: + + + + 437 + + + + useStandardKerning: + + + + 438 + + + + useStandardLigatures: + + + + 439 + + + + turnOffLigatures: + + + + 440 + + + + turnOffKerning: + + + + 441 + + + + toggleAutomaticSpellingCorrection: + + + + 456 + + + + orderFrontSubstitutionsPanel: + + + + 458 + + + + toggleAutomaticDashSubstitution: + + + + 461 + + + + toggleAutomaticTextReplacement: + + + + 463 + + + + uppercaseWord: + + + + 464 + + + + capitalizeWord: + + + + 467 + + + + lowercaseWord: + + + + 468 + + + + pasteAsPlainText: + + + + 486 + + + + performFindPanelAction: + + + + 487 + + + + performFindPanelAction: + + + + 488 + + + + performFindPanelAction: + + + + 489 + + + + showHelp: + + + + 493 + + + + alignCenter: + + + + 518 + + + + pasteRuler: + + + + 519 + + + + toggleRuler: + + + + 520 + + + + alignRight: + + + + 521 + + + + copyRuler: + + + + 522 + + + + alignJustified: + + + + 523 + + + + alignLeft: + + + + 524 + + + + makeBaseWritingDirectionNatural: + + + + 525 + + + + makeBaseWritingDirectionLeftToRight: + + + + 526 + + + + makeBaseWritingDirectionRightToLeft: + + + + 527 + + + + makeTextWritingDirectionNatural: + + + + 528 + + + + makeTextWritingDirectionLeftToRight: + + + + 529 + + + + makeTextWritingDirectionRightToLeft: + + + + 530 + + + + performFindPanelAction: + + + + 535 + + + + delegate + + + + 545 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 29 + + + + + + + + + + + + + + 19 + + + + + + + + 56 + + + + + + + + 217 + + + + + + + + 83 + + + + + + + + 81 + + + + + + + + + + + + + + + + + 75 + + + + + 78 + + + + + 72 + + + + + 82 + + + + + 124 + + + + + + + + 77 + + + + + 73 + + + + + 79 + + + + + 112 + + + + + 74 + + + + + 125 + + + + + + + + 126 + + + + + 205 + + + + + + + + + + + + + + + + + + + + + + 202 + + + + + 198 + + + + + 207 + + + + + 214 + + + + + 199 + + + + + 203 + + + + + 197 + + + + + 206 + + + + + 215 + + + + + 218 + + + + + + + + 216 + + + + + + + + 200 + + + + + + + + + + + + + 219 + + + + + 201 + + + + + 204 + + + + + 220 + + + + + + + + + + + + + 213 + + + + + 210 + + + + + 221 + + + + + 208 + + + + + 209 + + + + + 57 + + + + + + + + + + + + + + + + + + 58 + + + + + 134 + + + + + 150 + + + + + 136 + + + + + 144 + + + + + 129 + + + + + 143 + + + + + 236 + + + + + 131 + + + + + + + + 149 + + + + + 145 + + + + + 130 + + + + + 24 + + + + + + + + + + + 92 + + + + + 5 + + + + + 239 + + + + + 23 + + + + + 295 + + + + + + + + 296 + + + + + + + + + 297 + + + + + 298 + + + + + 211 + + + + + + + + 212 + + + + + + + + + 195 + + + + + 196 + + + + + 346 + + + + + 348 + + + + + + + + 349 + + + + + + + + + + + + + + 350 + + + + + 351 + + + + + 354 + + + + + 375 + + + + + + + + 376 + + + + + + + + + 377 + + + + + + + + 388 + + + + + + + + + + + + + + + + + + + + + + + 389 + + + + + 390 + + + + + 391 + + + + + 392 + + + + + 393 + + + + + 394 + + + + + 395 + + + + + 396 + + + + + 397 + + + + + + + + 398 + + + + + + + + 399 + + + + + + + + 400 + + + + + 401 + + + + + 402 + + + + + 403 + + + + + 404 + + + + + 405 + + + + + + + + + + + + 406 + + + + + 407 + + + + + 408 + + + + + 409 + + + + + 410 + + + + + 411 + + + + + + + + + + 412 + + + + + 413 + + + + + 414 + + + + + 415 + + + + + + + + + + + 416 + + + + + 417 + + + + + 418 + + + + + 419 + + + + + 450 + + + + + + + + 451 + + + + + + + + + + 452 + + + + + 453 + + + + + 454 + + + + + 457 + + + + + 459 + + + + + 460 + + + + + 462 + + + + + 465 + + + + + 466 + + + + + 485 + + + + + 490 + + + + + + + + 491 + + + + + + + + 492 + + + + + 496 + + + + + + + + 497 + + + + + + + + + + + + + + + + + 498 + + + + + 499 + + + + + 500 + + + + + 501 + + + + + 502 + + + + + 503 + + + + + + + + 504 + + + + + 505 + + + + + 506 + + + + + 507 + + + + + 508 + + + + + + + + + + + + + + + + 509 + + + + + 510 + + + + + 511 + + + + + 512 + + + + + 513 + + + + + 514 + + + + + 515 + + + + + 516 + + + + + 517 + + + + + 534 + + + + + 546 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 547 + + + + + AppDelegate + NSObject + + IBProjectSource + ../MacGap/AppDelegate.h + + + + + + NSApplication + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSApplication.h + + + + NSBrowser + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSBrowser.h + + + + NSControl + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSControl.h + + + + NSDocument + NSObject + + id + id + id + id + id + id + + + + printDocument: + id + + + revertDocumentToSaved: + id + + + runPageLayout: + id + + + saveDocument: + id + + + saveDocumentAs: + id + + + saveDocumentTo: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocument.h + + + + NSDocumentController + NSObject + + id + id + id + id + + + + clearRecentDocuments: + id + + + newDocument: + id + + + openDocument: + id + + + saveAllDocuments: + id + + + + IBFrameworkSource + AppKit.framework/Headers/NSDocumentController.h + + + + NSFormatter + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFormatter.h + + + + NSMatrix + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSMatrix.h + + + + NSMenu + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenu.h + + + + NSMenuItem + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSMenuItem.h + + + + NSMovieView + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSMovieView.h + + + + NSPopover + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSPopover.h + + + + NSResponder + NSObject + + IBFrameworkSource + AppKit.framework/Headers/NSResponder.h + + + + NSTableView + NSControl + + IBFrameworkSource + AppKit.framework/Headers/NSTableView.h + + + + NSText + NSView + + IBFrameworkSource + AppKit.framework/Headers/NSText.h + + + + NSTextView + NSText + + IBFrameworkSource + AppKit.framework/Headers/NSTextView.h + + + + NSView + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSView.h + + + + NSViewController + NSResponder + + view + NSView + + + view + + view + NSView + + + + IBFrameworkSource + AppKit.framework/Headers/NSViewController.h + + + + NSWindow + NSResponder + + IBFrameworkSource + AppKit.framework/Headers/NSWindow.h + + + + WebView + NSView + + id + id + id + id + id + id + id + id + id + id + id + + + + goBack: + id + + + goForward: + id + + + makeTextLarger: + id + + + makeTextSmaller: + id + + + makeTextStandardSize: + id + + + reload: + id + + + reloadFromOrigin: + id + + + stopLoading: + id + + + takeStringURLFrom: + id + + + toggleContinuousSpellChecking: + id + + + toggleSmartInsertDelete: + id + + + + IBFrameworkSource + WebKit.framework/Headers/WebView.h + + + + + 0 + IBCocoaFramework + NO + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + {12, 12} + {10, 2} + + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Window.xib b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Window.xib new file mode 100644 index 000000000..70d0c57b8 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/en.lproj/Window.xib @@ -0,0 +1,337 @@ + + + + 1070 + 11C74 + 1938 + 1138.23 + 567.00 + + YES + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + YES + 1938 + 822 + + + + YES + NSWindowTemplate + NSView + NSCustomObject + WebView + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + PluginDependencyRecalculationVersion + + + + YES + + WindowController + + + FirstResponder + + + NSApplication + + + 15 + 2 + {{196, 240}, {758, 410}} + 544735232 + Window + NSWindow + + + + + 256 + + YES + + + 274 + + YES + + YES + Apple HTML pasteboard type + Apple PDF pasteboard type + Apple PICT pasteboard type + Apple URL pasteboard type + Apple Web Archive pasteboard type + NSColor pasteboard type + NSFilenamesPboardType + NSStringPboardType + NeXT RTFD pasteboard type + NeXT Rich Text Format v1.0 pasteboard type + NeXT TIFF v4.0 pasteboard type + WebURLsWithTitlesPboardType + public.png + public.url + public.url-name + + + {758, 410} + + + + 2 + _NS:51 + + + + + + YES + + YES + WebKitDefaultFixedFontSize + WebKitDefaultFontSize + WebKitMinimumFontSize + + + YES + + + + + + + YES + YES + + + {758, 410} + + + + + {{0, 0}, {1920, 1178}} + {10000000000000, 10000000000000} + 128 + YES + + + + + YES + + + contentView + + + + 23 + + + + window + + + + 25 + + + + title: contentView.webView.mainFrameTitle + + + + + + title: contentView.webView.mainFrameTitle + title + contentView.webView.mainFrameTitle + 2 + + + 31 + + + + webView + + + + 19 + + + + + YES + + 0 + + YES + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + YES + + + + + + 2 + + + YES + + + + + + 5 + + + + + + + YES + + YES + -1.IBPluginDependency + -2.IBPluginDependency + -3.IBPluginDependency + 1.IBPluginDependency + 1.IBWindowTemplateEditedContentRect + 1.NSWindowTemplate.visibleAtLaunch + 2.CustomClassName + 2.IBPluginDependency + 5.IBPluginDependency + + + YES + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{357, 418}, {480, 270}} + + ContentView + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.WebKitIBPlugin + + + + YES + + + + + + YES + + + + + 31 + + + + YES + + ContentView + NSView + + webView + WebView + + + webView + + webView + WebView + + + + IBProjectSource + ./Classes/ContentView.h + + + + WebView + + reloadFromOrigin: + id + + + reloadFromOrigin: + + reloadFromOrigin: + id + + + + IBProjectSource + ./Classes/WebView.h + + + + WindowController + NSWindowController + + contentView + ContentView + + + contentView + + contentView + ContentView + + + + IBProjectSource + ./Classes/WindowController.h + + + + + 0 + IBCocoaFramework + + com.apple.InterfaceBuilder.CocoaPlugin.InterfaceBuilder3 + + + YES + 3 + + diff --git a/ext/mac-ui-macgap1-wrapper/MacGap/main.m b/ext/mac-ui-macgap1-wrapper/MacGap/main.m new file mode 100644 index 000000000..4ad50ad59 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/MacGap/main.m @@ -0,0 +1,14 @@ +// +// main.m +// MacGap +// +// Created by Alex MacCaw on 08/01/2012. +// Copyright (c) 2012 Twitter. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) +{ + return NSApplicationMain(argc, (const char **)argv); +} diff --git a/ext/mac-ui-macgap1-wrapper/README.md b/ext/mac-ui-macgap1-wrapper/README.md new file mode 100644 index 000000000..bc69b1326 --- /dev/null +++ b/ext/mac-ui-macgap1-wrapper/README.md @@ -0,0 +1,36 @@ +#MacGap + +The MacGap project provides HTML/JS/CSS developers an Xcode project for developing Native OSX Apps that run in OSX's WebView and take advantage of WebKit technologies. + +The project exposes a JavaScript API for OS X integration, such as displaying native OS X 10.9 notifications. The MacGap project is extremely lightweight and nimble; a blank application is about 980KB. + +### Features: +* tiny compiled app sizes +* Mac App Store compatible +* access to many Mac OS X-specific features + +##Pre-requisites + +MacGap works on OSX 10.6 and later. + +Generate apps with the [macgap generator](http://github.com/maccman/macgap-rb), no compile necessary. + + gem install macgap + + macgap new myapp + macgap build myapp + +##API + +MacGap exposes an object called `macgap` inside JavaScript. You can use it to alter the Dock icon and display Growl notifications, amongst other things. The API is documented in the WIKI on GitHub: https://github.com/maccman/macgap/wiki + + +##Attributes + +MacGap was forked/ported from Phonegap-mac. It's under the same license (MIT). + +##Custom Build + +To build, make sure you have installed the latest Mac OSX Core Library. Download at [http://developer.apple.com/](http://developer.apple.com/). + +Just clone the repository and build in Xcode. The file `public/index.html` is loaded on startup. diff --git a/ext/mac-ui-macgap1-wrapper/application.icns b/ext/mac-ui-macgap1-wrapper/application.icns new file mode 100644 index 0000000000000000000000000000000000000000..e4bcb2819c56c81aad36c3bf615e777727a0a158 GIT binary patch literal 88566 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%0A_FfiH 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

{XNhWAYG&mNkkWKeur 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 + + + MacGap + + + + + + + +

MacGap

+ + \ No newline at end of file diff --git a/ui/main.jsx b/ui/main.jsx index 01c300e99..aa4c8bf1c 100644 --- a/ui/main.jsx +++ b/ui/main.jsx @@ -1,4 +1,51 @@ +/* + * ZeroTier One - Network Virtualization Everywhere + * Copyright (C) 2011-2015 ZeroTier, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * -- + * + * ZeroTier may be used and distributed under the terms of the GPLv3, which + * are available at: http://www.gnu.org/licenses/gpl-3.0.html + * + * If you would like to embed ZeroTier into a commercial application or + * redistribute it in a modified binary form, please contact ZeroTier Networks + * LLC. Start here: http://www.zerotier.com/ + */ + +function getUrlParameter(parameter) +{ + var currLocation = window.location.search; + if (currLocation.indexOf('?') < 0) + return ''; + var parArr = currLocation.split("?")[1].split("&"); + for(var i = 0; i < parArr.length; i++){ + parr = parArr[i].split("="); + if (parr[0] == parameter) { + return decodeURIComponent(parr[1]); + } + } + return ''; +} + +var ztAuthToken = getUrlParameter('authToken'); +if ((!ztAuthToken)||(ztAuthToken.length <= 0)) { + ztAuthToken = prompt('No authToken specified in URL. Enter token from\nauthtoken.secret to authorize.'); +} + React.render( - , + , document.getElementById('main') );