├── .gitignore ├── .gitmodules ├── .ruby-version ├── .travis.yml ├── Frameworks └── NNKit │ ├── NNKit.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ └── NNKit.xcscheme │ ├── NNKit │ ├── API Extension │ │ ├── NSInvocation+NNCopying.h │ │ ├── NSInvocation+NNCopying.m │ │ ├── NSNotificationCenter+NNAdditions.h │ │ ├── NSNotificationCenter+NNAdditions.m │ │ ├── README.md │ │ ├── despatch.h │ │ ├── despatch.m │ │ ├── runtime.c │ │ └── runtime.h │ ├── Actors │ │ ├── NNCleanupProxy.h │ │ ├── NNCleanupProxy.m │ │ ├── NNMultiDispatchManager.h │ │ ├── NNMultiDispatchManager.m │ │ ├── NNPollingObject+Protected.h │ │ ├── NNPollingObject.h │ │ ├── NNPollingObject.m │ │ ├── NNSelfInvalidatingObject.h │ │ ├── NNSelfInvalidatingObject.m │ │ └── README.md │ ├── Collections │ │ ├── NNWeakSet.h │ │ ├── NNWeakSet.m │ │ ├── NSCollections+NNComprehensions.h │ │ ├── NSCollections+NNComprehensions.m │ │ ├── README.md │ │ ├── _NNWeakArrayTombstone.h │ │ ├── _NNWeakArrayTombstone.m │ │ ├── _NNWeakSetEnumerator.h │ │ └── _NNWeakSetEnumerator.m │ ├── Concurrency │ │ ├── NNDelegateProxy.h │ │ ├── NNDelegateProxy.m │ │ └── README.md │ ├── Hacks │ │ ├── NNStrongifiedProperties.h │ │ ├── NNStrongifiedProperties.m │ │ ├── README.md │ │ ├── memoize.h │ │ ├── memoize.m │ │ ├── nn_autofree.h │ │ └── nn_autofree.m │ ├── NNKit Mac-Prefix.pch │ ├── NNKit iOS-Prefix.pch │ ├── NNKit-Info.plist │ ├── NNKit.h │ ├── NNKit.m │ ├── Services │ │ ├── NNService+Protected.h │ │ ├── NNService.h │ │ ├── NNService.m │ │ ├── NNServiceManager.h │ │ ├── NNServiceManager.m │ │ └── README.md │ ├── Swizzling │ │ ├── NNISASwizzledObject.h │ │ ├── NNISASwizzledObject.m │ │ ├── README.md │ │ ├── nn_isaSwizzling.h │ │ ├── nn_isaSwizzling.m │ │ └── nn_isaSwizzling_Private.h │ └── macros.h │ ├── NNKitTests │ ├── NNCleanupProxyTests.m │ ├── NNComprehensionTests.m │ ├── NNDelegateProxyTests.m │ ├── NNKit Mac Tests-Info.plist │ ├── NNKit iOS Tests-Info.plist │ ├── NNMultiDispatchManagerTests.m │ ├── NNPollingObjectTests.m │ ├── NNSelfInvalidatingObjectTests.m │ ├── NNServiceTests.m │ ├── NNStrongifiedPropertiesTests.m │ ├── NNSynthesizedObjectStorageTests.m │ ├── NNTestCase.h │ ├── NNTestCase.m │ ├── NNWeakObserverTests.m │ ├── NNWeakSetTests.m │ ├── nn_autofreeTests.m │ └── nn_isaSwizzlingTests.m │ └── README.md ├── Podfile ├── Podfile.lock ├── README.md ├── Rakefile ├── Scripts ├── console.rb ├── reset_Accessibility.scpt └── sign_update.rb ├── Switch.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── WorkspaceSettings.xcsettings └── xcshareddata │ ├── xcbaselines │ └── BCA734FC16DAC54000CD4C74.xcbaseline │ │ ├── B10416B6-59AF-46B0-8C59-971F2DDC08B3.plist │ │ └── Info.plist │ └── xcschemes │ └── Switch.xcscheme ├── Switch.xcworkspace ├── contents.xcworkspacedata └── xcshareddata │ └── Switch.xcscmblueprint ├── Switch ├── NNMainThreadGuard.m ├── NSLayoutConstraint+SWConstraintHelpers.h ├── NSLayoutConstraint+SWConstraintHelpers.m ├── NSScreen+SWAdditions.h ├── NSScreen+SWAdditions.m ├── NSSet+SWChaining.h ├── NSSet+SWChaining.m ├── Resources │ ├── Keyboard.icns │ └── weave.png ├── SWAPIEnabledWorker.h ├── SWAPIEnabledWorker.m ├── SWAccessibilityService.h ├── SWAccessibilityService.m ├── SWAdvancedPreferencesViewController.h ├── SWAdvancedPreferencesViewController.m ├── SWAdvancedPreferencesViewController.xib ├── SWAppDelegate.h ├── SWAppDelegate.m ├── SWApplication.h ├── SWApplication.m ├── SWCoreWindowController.h ├── SWCoreWindowController.m ├── SWCoreWindowService.h ├── SWCoreWindowService.m ├── SWEventTap.h ├── SWEventTap.m ├── SWGeneralPreferencesViewController.h ├── SWGeneralPreferencesViewController.m ├── SWGeneralPreferencesViewController.xib ├── SWHUDCollectionView.h ├── SWHUDCollectionView.m ├── SWHUDView.h ├── SWHUDView.m ├── SWHotKey.h ├── SWHotKey.m ├── SWInterfaceController.h ├── SWInterfaceController.m ├── SWKeyboardPreferencesViewController.h ├── SWKeyboardPreferencesViewController.m ├── SWKeyboardPreferencesViewController.xib ├── SWLoggingService.h ├── SWLoggingService.m ├── SWPreferencesService.h ├── SWPreferencesService.m ├── SWRoundedRectView.h ├── SWRoundedRectView.m ├── SWScrollControl.h ├── SWScrollControl.m ├── SWSelectionBoxView.h ├── SWSelectionBoxView.m ├── SWSelector.h ├── SWSelector.m ├── SWStateMachine.h ├── SWStateMachine.m ├── SWStatusBarMenuService.h ├── SWStatusBarMenuService.m ├── SWWindow+TweetbotQuirks.h ├── SWWindow+TweetbotQuirks.m ├── SWWindow.h ├── SWWindow.m ├── SWWindowContentsService.h ├── SWWindowContentsService.m ├── SWWindowGroup.h ├── SWWindowGroup.m ├── SWWindowListService.h ├── SWWindowListService.m ├── SWWindowListWorker.h ├── SWWindowListWorker.m ├── SWWindowThumbnailView.h ├── SWWindowThumbnailView.m ├── SWWindowWorker.h ├── SWWindowWorker.m ├── Sparkle.dsa_pub.pem ├── Switch-Bridging-Header.h ├── Switch-Info.plist ├── Switch-Prefix.pch ├── Switch.entitlements ├── constants.h ├── constants.m ├── debugger.c ├── debugger.h ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ └── MainMenu.xib ├── helpers.h ├── helpers.m ├── imageComparators.h └── main.m ├── SwitchTests ├── NSImage+NNFilesystem.h ├── NSImage+NNFilesystem.m ├── NSWindow+NNScreenCapture.h ├── NSWindow+NNScreenCapture.m ├── References │ └── image.tiff ├── SWChromeTests.m ├── SWDashTests.m ├── SWFinderTests.m ├── SWGithubTests.m ├── SWImageComparisonTests.m ├── SWIsolatorTests.m ├── SWMacVimTests.m ├── SWPowerboxTests.m ├── SWSafariTests.m ├── SWSanityTests.m ├── SWScrollControlTests.m ├── SWSelectorTests.m ├── SWSheetTests.m ├── SWStateMachineTests.m ├── SWTestApplication.h ├── SWTestApplication.m ├── SWTweetbotTests.m ├── SWWindowFilteringTests.h ├── SWWindowListServiceTestSuperclass.h ├── SWWindowListServiceTestSuperclass.m ├── SWWindowListServiceTests.m ├── SWWordTests.m ├── SWXcodeTests.m ├── SwitchTests-Info.plist └── en.lproj │ ├── 1376.ar │ ├── 5891.ar │ ├── 5904.ar │ └── InfoPlist.strings ├── appcast.xml ├── exportOptionsApp.plist └── relaunch ├── SWTerminationListener.h ├── SWTerminationListener.m ├── main.m └── relaunch-Prefix.pch /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "Frameworks/Haxcessibility"] 2 | path = Frameworks/Haxcessibility 3 | url = git://github.com/numist/Haxcessibility.git 4 | [submodule "Frameworks/ReactiveCocoa"] 5 | path = Frameworks/ReactiveCocoa 6 | url = git://github.com/numist/ReactiveCocoa.git 7 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | ruby-2.1.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_project: Switch.xcodeproj 3 | xcode_scheme: Switch 4 | osx_image: xcode9 5 | 6 | before_script: 7 | - export LANG=en_US.UTF-8 8 | 9 | install: 10 | - gem install rake 11 | - rake deps 12 | 13 | script: 14 | - rake app 15 | - rake test 16 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/NSInvocation+NNCopying.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSInvocation+NNCopying.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 03/10/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface NSInvocation (NNCopying) 18 | 19 | - (instancetype)nn_copy; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/NSInvocation+NNCopying.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSInvocation+NNCopying.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 03/10/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSInvocation+NNCopying.h" 16 | 17 | @implementation NSInvocation (NNCopying) 18 | 19 | - (instancetype)nn_copy; 20 | { 21 | NSMethodSignature *signature = [self methodSignature]; 22 | NSUInteger const arguments = signature.numberOfArguments; 23 | 24 | NSInvocation *result = [NSInvocation invocationWithMethodSignature:signature]; 25 | 26 | void *heapBuffer = NULL; 27 | size_t heapBufferSize = 0; 28 | 29 | NSUInteger alignp = 0; 30 | for (NSUInteger i = 0; i < arguments; i++) { 31 | const char *type = [signature getArgumentTypeAtIndex:i]; 32 | NSGetSizeAndAlignment(type, NULL, &alignp); 33 | 34 | if (alignp > heapBufferSize) { 35 | heapBuffer = heapBuffer 36 | ? reallocf(heapBuffer, alignp) 37 | : malloc(alignp); 38 | heapBufferSize = alignp; 39 | } 40 | 41 | [self getArgument:heapBuffer atIndex:i]; 42 | [result setArgument:heapBuffer atIndex:i]; 43 | } 44 | 45 | if (heapBuffer) { 46 | free(heapBuffer); 47 | } 48 | 49 | result.target = self.target; 50 | 51 | if (self.argumentsRetained) { 52 | [result retainArguments]; 53 | } 54 | 55 | return result; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/NSNotificationCenter+NNAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSNotificationCenter+NNAdditions.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/14/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSNotificationCenter+NNAdditions.h" 16 | 17 | #import "NNCleanupProxy.h" 18 | 19 | 20 | @implementation NSNotificationCenter (NNAdditions) 21 | 22 | - (void)addWeakObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject; 23 | { 24 | NSString *key = [NSString stringWithFormat:@"%p-%@-%@-%p", anObject, NSStringFromSelector(aSelector), aName, self]; 25 | NNCleanupProxy *proxy = [NNCleanupProxy cleanupProxyForTarget:observer withKey:[key hash]]; 26 | 27 | __weak NSNotificationCenter *weakCenter = self; 28 | __unsafe_unretained NNCleanupProxy *unsafeProxy = proxy; 29 | 30 | [proxy cacheMethodSignatureForSelector:aSelector]; 31 | proxy.cleanupBlock = ^{ 32 | NSNotificationCenter *center = weakCenter; 33 | 34 | [center removeObserver:unsafeProxy name:aName object:anObject]; 35 | }; 36 | [self addObserver:proxy selector:aSelector name:aName object:anObject]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/README.md: -------------------------------------------------------------------------------- 1 | NNKit API Extensions 2 | ==================== 3 | 4 | For its own internal use, as well as your enjoyment, NNKit contains a set of extensions to existing system APIs. 5 | 6 | despatch 7 | -------- 8 | 9 | [Despatch](http://numist.net/define/?despatch) contains helper functions to make dealing with GCD easier. At the moment this is one function: 10 | 11 | ### `despatch_sync_main_reentrant` #### 12 | 13 | `despatch_sync_main_reentrant` is a function for making synchronous dispatch onto the main queue simpler. The block argument is invoked directly if the sender is already executing on the main thread, and dispatched synchronously onto the main queue otherwise. 14 | 15 | ### `despatch_group_yield` ### 16 | 17 | The yield concept is borrowed from Python and other languages as a way for a path of execution to pause and allow other work scheduled for that thread to proceed. In this case it's most useful in unit tests to allow asynchronous work that takes place on the main thread to proceed. 18 | 19 | A very basic example from `NNDelegateProxyTests.m`: 20 | 21 | - (void)testGlobalAsync; 22 | { 23 | dispatch_group_enter(group); 24 | [[[MYClass alloc] initWithDelegate:self] globalAsync]; 25 | 26 | NSDate *timeout = [NSDate dateWithTimeIntervalSinceNow:0.1]; 27 | while (!despatch_group_yield(group) && [[NSDate date] compare:timeout] == NSOrderedAscending); 28 | XCTAssertFalse(dispatch_group_wait(group, DISPATCH_TIME_NOW), @"Delegate message was never received (timed out)!"); 29 | } 30 | 31 | runtime 32 | ------- 33 | 34 | Runtime provides functions that should exist in the Objective-C runtime, but don't. 35 | 36 | ### `nn_selector_belongsToProtocol` ### 37 | 38 | `nn_selector_belongsToProtocol` returns whether or not a selector belongs to a protocol, with additional arguments that inform its search pattern and return information about the selector found in the protocol. Providing default values for `instance` and `required` begin the search with those attributes, and their values on return indicate the attributes of the first match found. 39 | 40 | NSNotificationCenter 41 | -------------------- 42 | 43 | The `NNAdditions` category to `NSNotificationCenter` adds a `addWeakObserver:selector:name:object:` method which references the observer weakly so no observer removal is required—it is automatically cleaned up when the observer is deallocated. 44 | 45 | NSInvocation 46 | ------------ 47 | 48 | The `NNCopying` category to `NSInvocation` adds an `nn_copy` method which returns a copy of the receiver. 49 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/despatch.h: -------------------------------------------------------------------------------- 1 | // 2 | // despatch.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #ifndef NNKit_despatch_h 16 | #define NNKit_despatch_h 17 | 18 | /*! 19 | * @function despatch_sync_main_reentrant 20 | * 21 | * @abstract 22 | * Runs a block on the main queue, reentrantly if already on the main queue. 23 | * 24 | * @discussion 25 | * When on the main queue, executes the block synchronously before returning. 26 | * Otherwise, submits a block to the main queue and does not return until the block 27 | * has finished. 28 | * 29 | * @param block 30 | * The block to be invoked on the main queue. 31 | * The result of passing NULL in this parameter is undefined. 32 | * Which is to say it will probably crash. 33 | */ 34 | void despatch_sync_main_reentrant(dispatch_block_t block); 35 | 36 | /*! 37 | * @function despatch_group_yield 38 | * 39 | * @abstract 40 | * Yields control of the current runloop. Return value indicates if the dispatch 41 | * group is clear. 42 | * 43 | * @discussion 44 | * When waiting for asynchronous jobs in a dispatch group that may block on the 45 | * current thread, this function yields the runloop and then returns the group 46 | * state. 47 | * 48 | * @param group 49 | * The group for which the caller is waiting. 50 | * 51 | * @result 52 | * YES if the group has no members, NO otherwise. 53 | */ 54 | BOOL despatch_group_yield(dispatch_group_t group); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/despatch.m: -------------------------------------------------------------------------------- 1 | // 2 | // despatch.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #include "despatch.h" 16 | 17 | 18 | void despatch_sync_main_reentrant(dispatch_block_t block) 19 | { 20 | if ([[NSThread currentThread] isMainThread]) { 21 | block(); 22 | } else { 23 | dispatch_sync(dispatch_get_main_queue(), block); 24 | } 25 | } 26 | 27 | BOOL despatch_group_yield(dispatch_group_t group) 28 | { 29 | // Let the runloop consume another event. 30 | NSRunLoop *currentRunLoop = [NSRunLoop currentRunLoop]; 31 | assert(currentRunLoop); // I sure have gotten paranoid in my old age. 32 | (void)[currentRunLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate date]]; 33 | 34 | // dispatch_group_wait docs say it returns zero or nonzero. Luckily, it needs to be inverted anyway, so a valid BOOL value gets enforced. 35 | return !dispatch_group_wait(group, DISPATCH_TIME_NOW); 36 | } 37 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/API Extension/runtime.c: -------------------------------------------------------------------------------- 1 | // 2 | // runtime.c 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #include "runtime.h" 16 | 17 | #include 18 | #include 19 | 20 | 21 | BOOL nn_selector_belongsToProtocol(SEL selector, Protocol *protocol, BOOL *requiredPtr, BOOL *instancePtr) 22 | { 23 | BOOL required = requiredPtr ? !!*requiredPtr : NO; 24 | BOOL instance = instancePtr ? !!*instancePtr : NO; 25 | 26 | for (int i = 0; i < (1 << 2); ++i) { 27 | BOOL checkRequired = required ^ (i & 1); 28 | BOOL checkInstance = instance ^ ((i & (1 << 1)) >> 1); 29 | 30 | struct objc_method_description hasMethod = protocol_getMethodDescription(protocol, selector, checkRequired, checkInstance); 31 | if (hasMethod.name || hasMethod.types) { 32 | if (requiredPtr) { 33 | *requiredPtr = checkRequired; 34 | } 35 | if (instancePtr) { 36 | *instancePtr = checkInstance; 37 | } 38 | return YES; 39 | } 40 | } 41 | 42 | return NO; 43 | } 44 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Actors/NNMultiDispatchManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNMultiDispatchManager.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface NNMultiDispatchManager : NSObject 19 | 20 | @property (nonatomic, assign, readwrite, getter = isEnabled, setter = setIsEnabled:) BOOL enabled; 21 | @property (nonatomic, readonly, assign) Protocol *protocol; 22 | 23 | - (instancetype)initWithProtocol:(Protocol *)protocol; 24 | 25 | - (void)addObserver:(id)observer; 26 | - (BOOL)hasObserver:(id)observer; 27 | - (void)removeObserver:(id)observer; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Actors/NNPollingObject+Protected.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNPollingObject+Protected.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 07/12/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface NNPollingObject (Protected) 19 | 20 | - (void)postNotification:(NSDictionary *)userInfo; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Actors/NNPollingObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNPollingObject.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 07/10/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface NNPollingObject : NSObject 19 | 20 | + (NSString *)notificationName; 21 | 22 | // I think this is the first time where I've wanted the default (atomic, assign, readwrite) flags for a property! 23 | // Too bad I have all warnings turned on: 24 | @property (atomic, assign, readwrite) NSTimeInterval interval; 25 | 26 | - (instancetype)initWithQueue:(dispatch_queue_t)queue; 27 | - (void)main; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Actors/NNSelfInvalidatingObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNSelfInvalidatingObject.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | /*! 19 | * @class NNSelfInvalidatingObject 20 | * 21 | * @discussion 22 | * For use when an object has to do cleanup work asynchronously, or outside of 23 | * dealloc. Simply implement the invalidate method and 24 | * call [super invalidate] when the actor has finished cleaning up. 25 | */ 26 | @interface NNSelfInvalidatingObject : NSObject 27 | 28 | /*! 29 | * @method invalidate 30 | * 31 | * @discussion 32 | * Called only once, either explicitly (by an interested object) or when the 33 | * object has been fully-released. 34 | * 35 | * When invalidation is complete, [super invalidate] must be called to complete 36 | * deallocation of the object. 37 | */ 38 | - (void)invalidate; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/NNWeakSet.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNWeakSet.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 06/04/16. 6 | // Copyright © 2016 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | /*! 18 | * @class NNMutableWeakSet 19 | * 20 | * @abstract 21 | * Provides a set-type collection that references its members weakly. 22 | * 23 | * @discussion 24 | * NNWeakSet implements the same API as NSMutableSet, but holds weak 25 | * references to its members. 26 | * 27 | * No compaction is required, members are automatically removed when they are 28 | * deallocated. 29 | * 30 | * This collection type may be slower than NSHashTable, but it also has 31 | * fewer bugs. 32 | */ 33 | @interface NNWeakSet : NSMutableSet 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/NSCollections+NNComprehensions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSArray+NNComprehensions.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 02/25/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | typedef BOOL (^nn_filter_block_t)(id item); 18 | typedef id (^nn_map_block_t)(id item); 19 | typedef id (^nn_reduce_block_t)(id accumulator, id item); 20 | 21 | @protocol NNCollection 22 | - (instancetype)nn_filter:(nn_filter_block_t)block; 23 | - (instancetype)nn_map:(nn_map_block_t)block; 24 | - (id)nn_reduce:(nn_reduce_block_t)block; 25 | @end 26 | 27 | @interface NSArray (NNComprehensions) 28 | @end 29 | 30 | @interface NSSet (NNComprehensions) 31 | @end 32 | 33 | @interface NSOrderedSet (NNComprehensions) 34 | @end 35 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/README.md: -------------------------------------------------------------------------------- 1 | # NNKit Collections # 2 | 3 | The code in this component gives collections superpowers. 4 | 5 | ## Category: NNComprehensions ## 6 | 7 | The `NNComprehensions` category on `NSArray`, `NSSet`, and `NSOrderedSet` implements the following comprehensions: 8 | 9 | ### nn_filter: ### 10 | Returns a new collection of the same (immutable) type that contains a subset of the items in the original array, as chosen by the method's argument, a block that takes an `id` and returns a `BOOL`. 11 | 12 | #### Example: #### 13 | ``` objective-c 14 | // Returns @[@3, @6, @9] 15 | [@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10] nn_filter:^(id item){ return (BOOL)!([item integerValue] % 3); }]; 16 | ``` 17 | 18 | ### nn_map: ### 19 | Returns a new collection of the same (immutable) type that contains new values based on the result of the block parameter, which takes an id and returns an id. 20 | 21 | Returning `nil` from the block is not supported. A separate filter step should be used first to remove unwanted items from the collection. 22 | 23 | #### Example: #### 24 | ``` objective-c 25 | // Returns @[@2, @4, @6, @8, @10, @12, @14, @16, @18, @20] 26 | [@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10] nn_map:^(id item){ return @([item integerValue] * 2); }]; 27 | ``` 28 | 29 | ### nn_reduce: ### 30 | Returns a reduction of the collection as defined by the block parameter, which takes an accumulator value (an `id` which starts as nil) and an item and returns the new value of the accumulator. 31 | 32 | #### Example: #### 33 | ``` objective-c 34 | // Returns @55 35 | [@[@1, @2, @3, @4, @5, @6, @7, @8, @9, @10] nn_reduce:^(id acc, id item){ return @([acc integerValue] + [item integerValue]); }]; 36 | ``` 37 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/_NNWeakArrayTombstone.h: -------------------------------------------------------------------------------- 1 | // 2 | // _NNWeakArrayTombstone.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface _NNWeakArrayTombstone : NSObject 19 | 20 | + (_NNWeakArrayTombstone *)tombstoneWithTarget:(id)target; 21 | 22 | @property (nonatomic, readonly, weak) id target; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/_NNWeakArrayTombstone.m: -------------------------------------------------------------------------------- 1 | // 2 | // _NNWeakArrayTombstone.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "_NNWeakArrayTombstone.h" 16 | 17 | 18 | @interface _NNWeakArrayTombstone () 19 | 20 | @property (nonatomic, readonly, assign) NSUInteger hash; 21 | 22 | @end 23 | 24 | 25 | @implementation _NNWeakArrayTombstone 26 | 27 | + (_NNWeakArrayTombstone *)tombstoneWithTarget:(id)target; 28 | { 29 | _NNWeakArrayTombstone *tombstone = [_NNWeakArrayTombstone new]; 30 | tombstone->_target = target; 31 | return tombstone; 32 | } 33 | 34 | @synthesize hash = _hash; 35 | - (NSUInteger)hash; 36 | { 37 | if (!self->_hash) { 38 | @synchronized(self) { 39 | if (!self->_hash) { 40 | id target = self.target; 41 | if (target) { 42 | self->_hash = [target hash]; 43 | } else { 44 | self->_hash = (uintptr_t)self; 45 | } 46 | } 47 | } 48 | } 49 | 50 | return self->_hash; 51 | } 52 | 53 | - (BOOL)isEqual:(id)object; 54 | { 55 | id target = self.target; 56 | return [target isEqual:object] ? YES : (uintptr_t)object == (uintptr_t)self; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/_NNWeakSetEnumerator.h: -------------------------------------------------------------------------------- 1 | // 2 | // _NNWeakSetEnumerator.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class NNWeakSet; 19 | 20 | 21 | @interface _NNWeakSetEnumerator : NSEnumerator 22 | 23 | - (instancetype)initWithWeakSet:(NNWeakSet *)set; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Collections/_NNWeakSetEnumerator.m: -------------------------------------------------------------------------------- 1 | // 2 | // _NNWeakSetEnumerator.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "_NNWeakSetEnumerator.h" 16 | 17 | #import "_NNWeakArrayTombstone.h" 18 | #import "NNWeakSet.h" 19 | 20 | 21 | @interface NNWeakSet (Private) 22 | 23 | @property (nonatomic, readonly, strong) NSSet *backingStore; 24 | 25 | @end 26 | 27 | 28 | @interface _NNWeakSetEnumerator () 29 | 30 | @property (nonatomic, readonly, strong) NSEnumerator *tombstoneEnumerator; 31 | 32 | @end 33 | 34 | 35 | @implementation _NNWeakSetEnumerator 36 | 37 | - (instancetype)initWithWeakSet:(NNWeakSet *)set; 38 | { 39 | if (!(self = [super init])) { return nil; } 40 | 41 | self->_tombstoneEnumerator = [set.backingStore.copy objectEnumerator]; 42 | 43 | return self; 44 | } 45 | 46 | - (NSArray *)allObjects; 47 | { 48 | NSMutableArray<_NNWeakArrayTombstone *> *result = [NSMutableArray new]; 49 | 50 | for (_NNWeakArrayTombstone *tombstone in self.tombstoneEnumerator.allObjects) { 51 | id obj = tombstone.target; 52 | if (obj) { 53 | [result addObject:obj]; 54 | } 55 | } 56 | 57 | return result; 58 | } 59 | 60 | - (id)nextObject; 61 | { 62 | id obj; 63 | _NNWeakArrayTombstone *tombstone; 64 | 65 | do { 66 | tombstone = self.tombstoneEnumerator.nextObject; 67 | obj = tombstone.target; 68 | } while (!obj && tombstone); 69 | 70 | return obj; 71 | } 72 | 73 | @end 74 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Concurrency/NNDelegateProxy.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNDelegateProxy.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | /*! 19 | * @class NNDelegateProxy 20 | * 21 | * @discussion 22 | * A proxy object ensuring that messages to the delegate are dispatched on the 23 | * main thread. 24 | * 25 | * Messages declared as oneway void are dispatched asynchronously, messages that 26 | * are optional are dispatched against nil if the delegate does not implement them. 27 | * Messages that are optional and non-void are a bad idea and you shouldn't use them. 28 | */ 29 | @interface NNDelegateProxy : NSProxy 30 | 31 | /*! 32 | * @method proxyWithDelegate:protocol: 33 | * 34 | * @discussion 35 | * Creates a new proxy for delegate conforming to 36 | * protocol. 37 | * 38 | * @param delegate 39 | * The object to receive delegate messages. 40 | * 41 | * @param protocol 42 | * The protocol to which delegate conforms. Can be NULL, 43 | * but shouldn't be. 44 | * 45 | * @result 46 | * Proxy to stand in for delegate for messages conforming to 47 | * protocol. 48 | */ 49 | + (id)proxyWithDelegate:(id)delegate protocol:(Protocol *)protocol; 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Concurrency/README.md: -------------------------------------------------------------------------------- 1 | NNKit Concurrency 2 | ================= 3 | 4 | NNKit provides tools to help make concurrency less of a headache, following the model of islands of serialization in a sea of concurrency. Since not all code can be expected to follow this model, NNKit also assumes that the only safe manner of passing messages between modules is on the main thread, and recievers are expected to get off the main thread as needed. 5 | 6 | NNDelegateProxy 7 | --------------- 8 | 9 | The `NNDelegateProxy` class provides a mechanism to ensure that all messages sent to a delegate are dispatched on the main thread. 10 | 11 | ### Example ### 12 | 13 | // You should already have a protocol for your use of the delegate pattern: 14 | @protocol MYClassDelegate 15 | - (void)objectCalledDelegateMethod:(id)obj; 16 | @end 17 | 18 | 19 | @interface MYClass : NSObject 20 | 21 | // And should already have a weak property for your delegate in your class declaration: 22 | @property (nonatomic, weak) id delegate; 23 | 24 | // Add a strong reference to a new property, the delegate proxy: 25 | @property (strong) id delegateProxy; 26 | 27 | @end 28 | 29 | @implementation MYClass 30 | 31 | - (instancetype)init; 32 | { 33 | if (!(self = [super init])) { return nil; } 34 | 35 | // Initialize the delegate proxy, feel free to set the delegate later if you don't have one handy. 36 | _delegateProxy = [NNDelegateProxy proxyWithDelegate:nil protocol:@protocol(MYClassDelegate)]; 37 | 38 | // … 39 | 40 | return self; 41 | } 42 | 43 | // If you have a writable delegate property, you'll need a custom delegate setter to ensure that the proxy gets updated: 44 | - (void)setDelegate:(id)delegate; 45 | { 46 | self->_delegate = delegate; 47 | 48 | ((NNDelegateProxy *)self.delegateProxy).delegate = delegate; 49 | // NOTE: A cast is necessary here because the delegateProxy property is typed id to retain as much static checking as possible elsewhere in your code, which fails here because the compiler doesn't realise that it's still an NNDelegateProxy under the hood. 50 | } 51 | 52 | - (void)method; 53 | { 54 | // Who cares how we got to where we are, or where that even is; when it's time to dispatch a delegate message just send it to the proxy: 55 | [self.delegateProxy objectCalledDelegateMethod:self]; 56 | } 57 | 58 | @end 59 | 60 | This proxy class was inspired by [Andy Matuschak](https://github.com/andymatuschak). 61 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/NNStrongifiedProperties.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNStrongifiedProperties.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | /*! 18 | * @class NNStrongifiedProperties 19 | * 20 | * @discussion 21 | * Used with isa-swizzling to provide strong getters for weak properties in the 22 | * form of methods named strongProperty, where 23 | * Property is the unambiguous capitalized name of a weak 24 | * property on the object. 25 | */ 26 | @interface NNStrongifiedProperties : NSObject 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/README.md: -------------------------------------------------------------------------------- 1 | NNKit Hacks 2 | =========== 3 | 4 | This portion of NNKit contains things that, while well-tested and reliable, shouldn't pass a sane person's test for acceptable complexity per unit utility. 5 | 6 | Automatically Freed C Buffers 7 | ----------------------------- 8 | 9 | Have a complicated function with a lot of logic and early returns? Avoid the possibility of forgetting to free your buffers with `nn_autofree`! 10 | 11 | @autoreleasepool { 12 | int *foo = nn_autofree(malloc(size)); 13 | } 14 | 15 | Don't forget, you're still in charge of NULLing your pointers, so it's easiest if you create your own autorelease pool, which will also create an extra scope for the buffer's pointer which it can't escape. 16 | 17 | Strongified Property Access 18 | --------------------------- 19 | 20 | Weak properties can be accessed with autoreleasing getters by either inheriting from or isa-swizzling `NNStrongifiedProperties`. 21 | 22 | @interface WeakDemo : NNStrongifiedProperties 23 | @property (weak) id foo; 24 | @end 25 | 26 | @interface WeakDemo (StrongAccessors) 27 | - (id)strongFoo; 28 | @end 29 | 30 | @implementation WeakDemo 31 | @end 32 | 33 | int main() { 34 | // Whenever you need an autoreleased reference to foo: 35 | [[WeakDemo new] strongFoo] 36 | } 37 | 38 | If you already inherit from a more useful class, this behaviour can be "learned" by an existing object by using isa swizzling: 39 | 40 | @interface WeakDemo : NSObject 41 | @property (weak) id foo; 42 | @end 43 | 44 | @interface WeakDemo (StrongAccessors) 45 | - (id)strongFoo; 46 | @end 47 | 48 | @implementation WeakDemo 49 | @end 50 | 51 | int main() { 52 | id obj = [WeakDemo new]; 53 | nn_object_swizzleIsa(obj, [NNStrongifiedProperties class]); 54 | 55 | // Whenever you need an autoreleased reference to foo: 56 | [obj strongFoo] 57 | } 58 | 59 | This hack was concieved after enabling the `-Wreceiver-is-weak` warning in clang and learning about the race condition it polices. 60 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/memoize.h: -------------------------------------------------------------------------------- 1 | // 2 | // memoize.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 06/23/15. 6 | // Copyright © 2015 Scott Perry. All rights reserved. 7 | // 8 | 9 | #define NNMemoize(block) _NNMemoize(self, _cmd, block) 10 | 11 | id _NNMemoize(id self, SEL _cmd, id (^block)()); 12 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/memoize.m: -------------------------------------------------------------------------------- 1 | // 2 | // memoize.c 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 06/23/15. 6 | // Copyright © 2015 Scott Perry. All rights reserved. 7 | // 8 | 9 | #import "memoize.h" 10 | 11 | #import 12 | 13 | 14 | id _NNMemoize(id self, SEL _cmd, id (^block)()) { 15 | id result; 16 | void *key = (void *)((uintptr_t)(__bridge void *)self ^ (uintptr_t)(void *)_cmd ^ (uintptr_t)&_NNMemoize); 17 | 18 | @synchronized(self) { 19 | result = objc_getAssociatedObject(self, key); 20 | if (!result) { 21 | result = block(); 22 | objc_setAssociatedObject(self, key, result, OBJC_ASSOCIATION_COPY_NONATOMIC); 23 | } 24 | } 25 | 26 | return result; 27 | } 28 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/nn_autofree.h: -------------------------------------------------------------------------------- 1 | // 2 | // nn_autofree.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/09/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | /*! 18 | * @function nn_autofree 19 | * 20 | * @abstract 21 | * Adds the buffer to the current autorelease pool. 22 | * 23 | * @discussion 24 | * This function ties the buffer's lifetime to that of an object added to the 25 | * current autorelease pool, causing it to be freed when the pool is drained. 26 | * 27 | * @param ptr 28 | * The buffer to add to the current autorelease pool. 29 | */ 30 | void *nn_autofree(void *ptr); 31 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Hacks/nn_autofree.m: -------------------------------------------------------------------------------- 1 | // 2 | // nn_autofree.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/09/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | // Requires -fno-objc-arc 15 | // 16 | 17 | #import "nn_autofree.h" 18 | 19 | void *nn_autofree(void *ptr) 20 | { 21 | if (ptr) { 22 | [NSData dataWithBytesNoCopy:ptr length:1 freeWhenDone:YES]; 23 | } 24 | return ptr; 25 | } 26 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/NNKit Mac-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/NNKit iOS-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/NNKit-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | net.numist.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | FMWK 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | NSHumanReadableCopyright 26 | Copyright © 2013 Scott Perry. All rights reserved. 27 | NSPrincipalClass 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/NNKit.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNKit.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | #import 18 | #import 19 | #import 20 | #import 21 | #import 22 | 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | 34 | #import 35 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/NNKit.m: -------------------------------------------------------------------------------- 1 | // 2 | // NNKit.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 09/05/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NNKit.h" 16 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Services/NNService+Protected.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNService+Protected.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 10/17/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class NNMultiDispatchManager; 19 | 20 | 21 | @interface NNService (Protected) 22 | 23 | @property (atomic, readonly, strong) NNMultiDispatchManager *subscriberDispatcher; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Services/NNService.m: -------------------------------------------------------------------------------- 1 | // 2 | // NNService.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 10/17/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NNService+Protected.h" 16 | 17 | #import "NNServiceManager.h" 18 | #import "NNMultiDispatchManager.h" 19 | 20 | 21 | @interface NNService () 22 | 23 | @property (atomic, readonly, strong) NNMultiDispatchManager *subscriberDispatcher; 24 | 25 | @end 26 | 27 | 28 | @implementation NNService 29 | 30 | + (instancetype)sharedService; 31 | { 32 | static NSMutableDictionary *instances; 33 | 34 | static dispatch_once_t onceToken; 35 | dispatch_once(&onceToken, ^{ 36 | instances = [NSMutableDictionary new]; 37 | }); 38 | 39 | NNService *result; 40 | 41 | @synchronized(instances) { 42 | result = [instances objectForKey:self]; 43 | if (!result) { 44 | result = [self new]; 45 | [instances setObject:result forKey:self]; 46 | } 47 | } 48 | 49 | return result; 50 | } 51 | 52 | + (NNServiceType)serviceType; 53 | { 54 | return NNServiceTypePersistent; 55 | } 56 | 57 | + (NSSet *)dependencies; 58 | { 59 | return [NSSet set]; 60 | } 61 | 62 | + (Protocol *)subscriberProtocol; 63 | { 64 | return @protocol(NSObject); 65 | } 66 | 67 | - (id)init; 68 | { 69 | if (!(self = [super init])) { return nil; } 70 | 71 | self->_subscriberDispatcher = [[NNMultiDispatchManager alloc] initWithProtocol:self.class.subscriberProtocol]; 72 | 73 | return self; 74 | } 75 | 76 | - (void)startService; 77 | { 78 | NSAssert([[NSThread currentThread] isMainThread], @"Service must be started on the main thread"); 79 | } 80 | 81 | - (void)stopService; 82 | { 83 | NSAssert([[NSThread currentThread] isMainThread], @"Service must be stopped on the main thread"); 84 | } 85 | 86 | @end 87 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Services/README.md: -------------------------------------------------------------------------------- 1 | NNKit Services 2 | ============== 3 | 4 | NNKit provides a framework for services running in your application, including dependency management, subscriber and observer dispatch, automatic starting and stopping of services based on subscriptions, and an easy mechanism to register all the services in your application in your app delegate, keeping your code small and readable. 5 | 6 | What makes a service 7 | -------------------- 8 | 9 | Services are classes that inherit from `NNService` and respond to `serviceType` with a type other than `NNServiceTypeNone`. The other two types are: 10 | 11 | * `NNServiceTypePersistent`: the service will run as long as its dependencies (if any) are running. 12 | * `NNServiceTypeOnDemand`: the service will run as long as its dependencies (if any) are running and at least one object has subscribed to the service using the service manager's `addSubscriber:forService:` method. 13 | 14 | Dependency management 15 | --------------------- 16 | 17 | Service dependencies are defined by the `dependencies` method, which returns an NSSet of class objects. Dependencies that are not already known to the service manager will be added automatically if possible. 18 | 19 | Subscriber (and observer) message dispatch 20 | ------------------------------------------ 21 | 22 | Services whose instances dispatch messages to their subscribers must respond to `subscriberProtocol` with the appropriate protocol. Subscribers must conform to this protocol and will be checked at runtime. Sending a message to subscribers can be accomplished with code resembling the following: 23 | 24 | ``` objective-c 25 | - (void)sendMessage; 26 | { 27 | [(id)self.subscriberDispatcher serviceWillDoThing:self]; 28 | } 29 | ``` 30 | 31 | Convenience hacks 32 | ----------------- 33 | 34 | Automatically adding all services known to the runtime is accomplished by calling `registerAllPossibleServices` on a service manager, preferably the `sharedManager`. 35 | 36 | Would you like to know more? 37 | ---------------------------- 38 | 39 | For a deeper dive into services, check out the [unit tests](https://github.com/numist/NNKit/blob/master/NNKitTests/NNServiceTests.m). 40 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Swizzling/NNISASwizzledObject.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNISASwizzledObject.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 02/07/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @protocol NNISASwizzledObject @end 19 | 20 | 21 | @interface NNISASwizzledObject : NSObject 22 | 23 | + (void)prepareObjectForSwizzling:(NSObject *)anObject; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Swizzling/README.md: -------------------------------------------------------------------------------- 1 | NNKit Swizzling 2 | =============== 3 | 4 | NNKit provides robust, general-purpose swizzling utilities. 5 | 6 | If you think this is a good idea, you should probably stop and make sure that your needs are not a symptom of more severe architectural problems. 7 | 8 | Isa Swizzling 9 | ------------- 10 | 11 | Robust isa swizzling is provided using the `nn_object_swizzleIsa` function. The following conditions must be met: 12 | 13 | * The object is an instance of the swizzling class's superclass, or a subclass of the swizzling class's superclass. 14 | * The swizzling class does not add any ivars or non-dynamic properties. 15 | 16 | An object has been swizzled by a class if it responds YES to `isKindOfClass:` with the swizzling class as an argument. Protocols can also be used, and queried using `conformsToProtocol:`, as usual. 17 | 18 | To avoid any confusion, your swizzling class should not implement an allocator or initializer. They will never be called for swizzled objects. 19 | 20 | ### Usage ### 21 | 22 | First, you'll need to define your swizzling class. For example: 23 | 24 | @interface MYClass : NSObject 25 | @property (nonatomic, readonly) NSUInteger random; 26 | - (void)duck; 27 | @end 28 | 29 | @implementation MYClass 30 | - (NSUInteger)random { return 7; } 31 | - (void)duck { NSLog(@"quack!"); } 32 | - (void)dog { NSLog(@"woof!"); } 33 | @end 34 | 35 | To swizzle your object and use its newfound functionality, just call `nn_object_swizzleIsa`: 36 | 37 | #import 38 | 39 | @implementation MYCode 40 | - (void)main { 41 | NSObject *bar = [[NSObject alloc] init]; 42 | nn_object_swizzleIsa(bar, [MYClass class]); 43 | if ([bar isKindOfClass:[MYClass class]]) { 44 | [(MYClass *)bar duck]; 45 | } 46 | if ([bar conformsToProtocol:@protocol(NSDog)]) { 47 | [(id)bar dog]; 48 | } 49 | } 50 | @end 51 | 52 | See the tests for more explicit examples of what is supposed to work and what is supposed to be an error. 53 | 54 | Credits 55 | ======= 56 | 57 | If not for [Rob Rix](https://github.com/robrix/), the Swizzling component of NNKit would not exist. Which probably would have been a good thing. 58 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Swizzling/nn_isaSwizzling.h: -------------------------------------------------------------------------------- 1 | // 2 | // nn_isaSwizzling.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 02/07/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | /*! 19 | * @function nn_object_swizzleIsa 20 | * 21 | * @abstract 22 | * Swizzles the class of obj to a dynamic subclass including the 23 | * qualities of swizzlingClass. 24 | * 25 | * @discussion 26 | * This function implements generic isa swizzling assuming the following conditions are met: 27 | * • A protocol with the same name as swizzlingClass exists and is 28 | * implemented by swizzlingClass. 29 | * • obj is an instance of the swizzlingClass's 30 | * superclass, or a subclass of swizzlingClass's superclass. 31 | * • swizzlingClass does not add any ivars or non-dynamic properties. 32 | * 33 | * An object has been swizzled by a class if it conforms to that class's 34 | * complementing protocol, allowing you to cast the object (after checking!) to 35 | * a type that explicitly implements the protocol. 36 | * 37 | * For more details about use, see the tests in nn_isaSwizzlingTests.m. 38 | * 39 | * @param obj 40 | * The object to be swizzled. 41 | * 42 | * @param swizzlingClass 43 | * The class to apply to obj. 44 | */ 45 | BOOL nn_object_swizzleIsa(id obj, Class swizzlingClass) __attribute__((nonnull(1, 2))); 46 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/Swizzling/nn_isaSwizzling_Private.h: -------------------------------------------------------------------------------- 1 | // 2 | // nn_isaSwizzling_Private.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 02/08/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | BOOL nn_alreadySwizzledObjectWithSwizzlingClass(id anObject, Class aClass) __attribute__((nonnull(1, 2))); 18 | 19 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKit/macros.h: -------------------------------------------------------------------------------- 1 | // 2 | // macros.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 02/25/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #pragma once 16 | 17 | // Compile-time key path additions 18 | #define NNKeyPath(object, keyPath) ({ if (NO) { (void)((object).keyPath); } @#keyPath; }) 19 | #define NNSelfKeyPath(keyPath) NNKeyPath(self, keyPath) 20 | #define NNTypedKeyPath(ObjectClass, keyPath) NNKeyPath(((ObjectClass *)nil), keyPath) 21 | #define NNProtocolKeyPath(Protocol, keyPath) NNKeyPath(((id )nil), keyPath) 22 | 23 | // Compile-time selector additions 24 | #define NNSelector(object, selectorName) ({ if (NO) { (void)[(object) selectorName]; } @selector(selectorName); }) 25 | #define NNSelfSelector(selectorName) NNSelector(self, selectorName) 26 | #define NNTypedSelector(ObjectClass, selectorName) NNSelector(((ObjectClass *)nil), selectorName) 27 | #define NNProtocolSelector(Protocol, selectorName) NNSelector(((id )nil), selectorName) 28 | 29 | #define NNSelector1(object, selectorName) ({ if (NO) { (void)[(object) selectorName nil]; } @selector(selectorName); }) 30 | #define NNSelfSelector1(selectorName) NNSelector1(self, selectorName) 31 | #define NNTypedSelector1(ObjectClass, selectorName) NNSelector1(((ObjectClass *)nil), selectorName) 32 | #define NNProtocolSelector1(Protocol, selectorName) NNSelector1(((id )nil), selectorName) 33 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/NNKit Mac Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | net.numist.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/NNKit iOS Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | net.numist.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/NNTestCase.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNTestCase.h 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/20/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface NNTestCase : XCTestCase 18 | 19 | - (BOOL)testForMemoryLeaksWithBlock:(void (^)())block iterations:(size_t)iterations; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/NNTestCase.m: -------------------------------------------------------------------------------- 1 | // 2 | // NNTestCase.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/20/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NNTestCase.h" 16 | 17 | #import 18 | 19 | 20 | static size_t report_memory(void) { 21 | struct task_basic_info info; 22 | mach_msg_type_number_t size = sizeof(info); 23 | kern_return_t kerr = task_info(mach_task_self(), 24 | TASK_BASIC_INFO, 25 | (task_info_t)&info, 26 | &size); 27 | if( kerr != KERN_SUCCESS ) { 28 | @throw [NSException exceptionWithName:@"wtf" reason:[NSString stringWithFormat:@"Error with task_info(): %s", mach_error_string(kerr)] userInfo:nil]; 29 | } 30 | return info.resident_size; 31 | } 32 | 33 | 34 | @interface NNTestCase () 35 | 36 | @end 37 | 38 | 39 | @implementation NNTestCase 40 | 41 | - (BOOL)testForMemoryLeaksWithBlock:(void (^)())block iterations:(size_t)iterations; 42 | { 43 | XCTAssertTrue(iterations > 4096, @"Memory leak tests are not accurate with iteration counts less than 4096!"); 44 | 45 | // Three bytes per iteration is allowed to leak because that's basically impossible. 46 | size_t bytes_expected = iterations * 3; 47 | size_t memory_usage_at_start = report_memory(); 48 | 49 | while (--iterations != 0) { 50 | @autoreleasepool { 51 | block(); 52 | } 53 | } 54 | 55 | size_t bytes_actual = report_memory() - memory_usage_at_start; 56 | BOOL memory_usage_is_good = bytes_actual < bytes_expected; 57 | NSLog(@"Memory usage increased by %zu bytes by end of test", bytes_actual); 58 | XCTAssertTrue(memory_usage_is_good, @"Memory usage increased by %zu bytes by end of test (expected < %zu)", bytes_actual, bytes_expected); 59 | 60 | return memory_usage_is_good; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/NNWeakObserverTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NNWeakObserverTests.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/14/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | #import 18 | 19 | 20 | static NSString *notificationName = @"somenotification"; 21 | unsigned receivedNotifications; 22 | 23 | 24 | @interface _NNWeakObserverTestObserver : NSObject 25 | @end 26 | @implementation _NNWeakObserverTestObserver 27 | - (void)notify:(NSNotification *)note; 28 | { 29 | receivedNotifications++; 30 | } 31 | - (void)dealloc; 32 | { 33 | NSLog(@"Destroyed object!"); 34 | } 35 | @end 36 | 37 | 38 | @interface NNWeakObserverTests : XCTestCase 39 | 40 | @end 41 | 42 | 43 | @implementation NNWeakObserverTests 44 | 45 | - (void)setUp 46 | { 47 | [super setUp]; 48 | 49 | receivedNotifications = 0; 50 | } 51 | 52 | - (void)testWeakObservers 53 | { 54 | @autoreleasepool { 55 | __attribute__((objc_precise_lifetime)) _NNWeakObserverTestObserver *observer = [_NNWeakObserverTestObserver new]; 56 | [[NSNotificationCenter defaultCenter] addWeakObserver:observer selector:@selector(notify:) name:notificationName object:nil]; 57 | [[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self]; 58 | XCTAssertEqual(receivedNotifications, (unsigned)1, @""); 59 | } 60 | XCTAssertNoThrow([[NSNotificationCenter defaultCenter] postNotificationName:notificationName object:self], @""); 61 | XCTAssertEqual(receivedNotifications, (unsigned)1, @""); 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /Frameworks/NNKit/NNKitTests/nn_autofreeTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // nn_autofreeTests.m 3 | // NNKit 4 | // 5 | // Created by Scott Perry on 11/20/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NNTestCase.h" 16 | 17 | #import 18 | 19 | 20 | @interface nn_autofreeTests : NNTestCase 21 | 22 | @end 23 | 24 | 25 | @implementation nn_autofreeTests 26 | 27 | - (void)setUp 28 | { 29 | [super setUp]; 30 | // Put setup code here. This method is called before the invocation of each test method in the class. 31 | } 32 | 33 | - (void)tearDown 34 | { 35 | // Put teardown code here. This method is called after the invocation of each test method in the class. 36 | [super tearDown]; 37 | } 38 | 39 | - (void)testExample 40 | { 41 | [self testForMemoryLeaksWithBlock:^{ 42 | nn_autofree(malloc(2)); 43 | } iterations:1e5]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Frameworks/NNKit/README.md: -------------------------------------------------------------------------------- 1 | NNKit 2 | ===== 3 | 4 | This library represents a collection of well-tested, robust, occasionally idiotic, but always well-meaning widgets for the Objective-C developer. 5 | 6 | At the moment it is a poorly-documented collection of code samples for my [NSMeetup talk](http://www.meetup.com/nsmeetup/events/136648202/) as well as a shared repository of solutions to common problems for [Switch](https://github.com/numist/Switch) and tmbo, the latter being a sort of promise to keep on adding, testing, and documenting the framework. 7 | 8 | The framework is broken up by purpose, the most entertaining of which are likely [Swizzling](https://github.com/numist/NNKit/tree/master/NNKit/Swizzling) and [Hacks](https://github.com/numist/NNKit/tree/master/NNKit/Hacks). 9 | -------------------------------------------------------------------------------- /Podfile: -------------------------------------------------------------------------------- 1 | source 'https://github.com/CocoaPods/Specs.git' 2 | platform :osx, '10.10' 3 | 4 | target :Switch do 5 | pod 'MASPreferences' 6 | pod 'Sparkle' 7 | target :SwitchTests do 8 | pod 'OCMock' 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - MASPreferences (1.1.4) 3 | - OCMock (3.1.2) 4 | - Sparkle (1.14.0) 5 | 6 | DEPENDENCIES: 7 | - MASPreferences 8 | - OCMock 9 | - Sparkle 10 | 11 | SPEC REPOS: 12 | https://github.com/CocoaPods/Specs.git: 13 | - MASPreferences 14 | - OCMock 15 | - Sparkle 16 | 17 | SPEC CHECKSUMS: 18 | MASPreferences: 7bdcfe891d7840453cf48f95fa866c3e152ace7a 19 | OCMock: a10ea9f0a6e921651f96f78b6faee95ebc813b92 20 | Sparkle: ccd95233b12a3e3d4eeb55ff01dd4c8bb8188b07 21 | 22 | PODFILE CHECKSUM: f98179f647f587219a5246f66f8624262c7dd81d 23 | 24 | COCOAPODS: 1.9.3 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Switch, Window-Based Context Switching 2 | ====================================== 3 | 4 | Switch is a window-based (as opposed to application-based) context switcher. By default it is bound to using `⌥⇥` and `⌥⇧⇥` to cycle through the visible windows on the current space. When the interface is active, `⌥W` can be used to close windows and `⌥,` used to show a preferences window. The main interface looks like this: 5 | 6 | ![Interface Screenshot](http://numist.net/random/switch.png) 7 | 8 | This project is functional, but not finished. That said, I've been using it every day. 9 | 10 | [Patches](https://github.com/numist/Switch/pull/new) and [issues](https://github.com/numist/Switch/issues) are welcome. If a window is being improperly shown or omitted from the interface, please include a [snapshot](https://github.com/numist/Switch/wiki/About-Snapshots). 11 | 12 | Getting Started 13 | --------------- 14 | 15 | Download the [latest release](https://github.com/numist/Switch/releases), put the application bundle in your `/Applications` or `~/Applications` directory, and run it! It will check for updates automatically so you can stay up to date as the project develops. 16 | 17 | Switch requires Mac OS X version 10.14 or newer and is still in development. For a list of known issues, check out the [bug tag](https://github.com/numist/Switch/issues?labels=bug&state=open) for general badness and the [quirk tag](https://github.com/numist/Switch/issues?labels=quirk&state=open) for windows being improperly shown or omitted from the interface. 18 | 19 | Contributing 20 | ------------ 21 | 22 | [![Build Status](https://travis-ci.org/numist/Switch.png?branch=develop)](https://travis-ci.org/numist/Switch) 23 | 24 | To check out the project, its submodules, and open in Xcode: 25 | 26 | git clone git://github.com/numist/Switch.git 27 | cd Switch/ 28 | rake deps 29 | open Switch.xcworkspace 30 | 31 | At this point, `⌘R` should have you up and running! 32 | 33 | The release process uses the project `Rakefile`; if you have a Developer ID certificate installed, you should be able to run `rake release` without any issues. Without a Developer ID, the `analyze`, `test`, and `app` targets (and their dependencies) should succeed. 34 | 35 | Thanks! 36 | ------- 37 | 38 | Switch relies on a number of external frameworks, either as [submodules](https://github.com/numist/Switch/tree/develop/Frameworks) or [pods](https://github.com/numist/Switch/tree/develop/Podfile). Thanks to the people responsible for them, you've saved me time and tears. 39 | -------------------------------------------------------------------------------- /Scripts/console.rb: -------------------------------------------------------------------------------- 1 | 2 | $stdout.sync = true 3 | 4 | class Console 5 | @@line_length = 0 6 | 7 | def self.append(text) 8 | # TODO blow up if "\r" is found or something 9 | text_without_colors = text.gsub(/\e\[[\d]+(;[\d]+)*m/, "") 10 | last_newline_index = text_without_colors.rindex "\n" 11 | if last_newline_index.nil? 12 | @@line_length += text.length 13 | else 14 | @@line_length = text.length - (last_newline_index + 1) 15 | end 16 | 17 | $stdout.print text 18 | end 19 | 20 | def self.clear_line 21 | # clear the old line 22 | if @@line_length > 0 23 | spaces = "" 24 | @@line_length.times { spaces = "#{spaces} " } 25 | $stdout.print "\r#{spaces}\r" 26 | @@line_length = 0 27 | end 28 | end 29 | 30 | def self.print(text) 31 | clear_line 32 | append text 33 | end 34 | 35 | def self.puts(text) 36 | print "#{text}\n" 37 | end 38 | 39 | # Colours: 40 | # 0 Turn off all attributes 41 | # 1 Set bright mode 42 | # 4 Set underline mode 43 | # 5 Set blink mode 44 | # 7 Exchange foreground and background colors 45 | # 8 Hide text (foreground color would be the same as background) 46 | # 30 Black text 47 | # 31 Red text 48 | # 32 Green text 49 | # 33 Yellow text 50 | # 34 Blue text 51 | # 35 Magenta text 52 | # 36 Cyan text 53 | # 37 White text 54 | # 39 Default text color 55 | # 40 Black background 56 | # 41 Red background 57 | # 42 Green background 58 | # 43 Yellow background 59 | # 44 Blue background 60 | # 45 Magenta background 61 | # 46 Cyan background 62 | # 47 White background 63 | # 49 Default background color 64 | 65 | def self.background_red(text) 66 | return "\e[41m#{text}\e[49m" 67 | end 68 | 69 | def self.background_white(text) 70 | return "\e[47m#{text}\e[49m" 71 | end 72 | 73 | def self.bold(text) 74 | return "\e[1m#{text}\e[0m" 75 | end 76 | 77 | def self.cyan(text) 78 | return "\e[36m#{text}\e[39m" 79 | end 80 | 81 | def self.black(text) 82 | return "\e[30m#{text}\e[39m" 83 | end 84 | 85 | def self.green(text) 86 | return "\e[32m#{text}\e[39m" 87 | end 88 | 89 | def self.white(text) 90 | return "\e[37m#{text}\e[39m" 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /Scripts/reset_Accessibility.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/Scripts/reset_Accessibility.scpt -------------------------------------------------------------------------------- /Scripts/sign_update.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/ruby 2 | if ARGV.length < 2 3 | puts "Usage: ruby sign_update.rb update_archive private_key" 4 | exit 5 | end 6 | 7 | puts `openssl dgst -sha1 -binary < "#{ARGV[0]}" | openssl dgst -dss1 -sign "#{ARGV[1]}" | openssl enc -base64` -------------------------------------------------------------------------------- /Switch.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Switch.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Switch.xcodeproj/xcshareddata/xcbaselines/BCA734FC16DAC54000CD4C74.xcbaseline/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runDestinationsByUUID 6 | 7 | B10416B6-59AF-46B0-8C59-971F2DDC08B3 8 | 9 | localComputer 10 | 11 | busSpeedInMHz 12 | 100 13 | cpuCount 14 | 1 15 | cpuKind 16 | Intel Core i7 17 | cpuSpeedInMHz 18 | 2000 19 | logicalCPUCoresPerPackage 20 | 4 21 | modelCode 22 | MacBookAir5,1 23 | physicalCPUCoresPerPackage 24 | 2 25 | platformIdentifier 26 | com.apple.platform.macosx 27 | 28 | targetArchitecture 29 | x86_64 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /Switch.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Switch/NSLayoutConstraint+SWConstraintHelpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSLayoutConstraint+SWConstraintHelpers.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/22/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface NSLayoutConstraint (SWConstraintHelpers) 18 | 19 | + (NSArray *)sw_constraintsCenteringView:(NSView *)view toView:(NSView *)anchor; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Switch/NSLayoutConstraint+SWConstraintHelpers.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSLayoutConstraint+SWConstraintHelpers.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/22/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSLayoutConstraint+SWConstraintHelpers.h" 16 | 17 | @implementation NSLayoutConstraint (SWConstraintHelpers) 18 | 19 | + (NSArray *)sw_constraintsCenteringView:(NSView *)view toView:(NSView *)anchor; 20 | { 21 | return @[ 22 | [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterX 23 | relatedBy:NSLayoutRelationEqual 24 | toItem:anchor attribute:NSLayoutAttributeCenterX 25 | multiplier:1.f constant:0.f], 26 | 27 | [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeCenterY 28 | relatedBy:NSLayoutRelationEqual 29 | toItem:anchor attribute:NSLayoutAttributeCenterY 30 | multiplier:1.f constant:0.f] 31 | ]; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Switch/NSScreen+SWAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+SWAdditions.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/29/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface NSScreen (SWAdditions) 19 | 20 | + (CGFloat)sw_totalScreenHeight; 21 | 22 | - (CGDirectDisplayID)sw_screenNumber; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Switch/NSScreen+SWAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSScreen+SWAdditions.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/29/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSScreen+SWAdditions.h" 16 | 17 | 18 | @implementation NSScreen (SWAdditions) 19 | 20 | + (CGFloat)sw_totalScreenHeight; 21 | { 22 | return [[[NSScreen screens] nn_reduce:^id(id accumulator, id item) { 23 | if (!accumulator) { accumulator = @(0.0); } 24 | CGRect screenFrame = [item private_sw_absoluteFrame]; 25 | CGFloat screenHeight = screenFrame.origin.y + screenFrame.size.height; 26 | if ([accumulator floatValue] < screenFrame.origin.y + screenFrame.size.height) { 27 | accumulator = @(screenHeight); 28 | } 29 | return accumulator; 30 | }] floatValue]; 31 | } 32 | 33 | - (CGDirectDisplayID)sw_screenNumber; 34 | { 35 | NSDictionary *description = self.deviceDescription; 36 | return [description[@"NSScreenNumber"] unsignedIntValue]; 37 | } 38 | 39 | - (CGRect)private_sw_absoluteFrame; 40 | { 41 | CGPoint offset = CGPointZero; 42 | for (NSScreen *screen in [NSScreen screens]) { 43 | if (screen.frame.origin.x < offset.x) { 44 | offset.x = screen.frame.origin.x; 45 | } 46 | if (screen.frame.origin.y < offset.y) { 47 | offset.y = screen.frame.origin.y; 48 | } 49 | } 50 | 51 | CGRect result = self.frame; 52 | result.origin.x -= offset.x; 53 | result.origin.y -= offset.y; 54 | return result; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Switch/NSSet+SWChaining.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSSet+SWChaining.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/22/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface NSSet (SWChaining) 19 | 20 | - (instancetype)sw_unionSet:(NSSet *)otherSet; 21 | - (instancetype)sw_minusSet:(NSSet *)otherSet; 22 | - (instancetype)sw_intersectSet:(NSSet *)otherSet; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Switch/NSSet+SWChaining.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSSet+SWChaining.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/22/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSSet+SWChaining.h" 16 | 17 | 18 | @implementation NSSet (SWChaining) 19 | 20 | - (instancetype)sw_unionSet:(NSSet *)otherSet; 21 | { 22 | NSMutableSet *result = [self mutableCopy]; 23 | [result unionSet:otherSet]; 24 | return result; 25 | } 26 | 27 | - (instancetype)sw_minusSet:(NSSet *)otherSet; 28 | { 29 | NSMutableSet *result = [self mutableCopy]; 30 | [result minusSet:otherSet]; 31 | return result; 32 | } 33 | 34 | - (instancetype)sw_intersectSet:(NSSet *)otherSet; 35 | { 36 | NSMutableSet *result = [self mutableCopy]; 37 | [result intersectSet:otherSet]; 38 | return result; 39 | } 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /Switch/Resources/Keyboard.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/Switch/Resources/Keyboard.icns -------------------------------------------------------------------------------- /Switch/Resources/weave.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/Switch/Resources/weave.png -------------------------------------------------------------------------------- /Switch/SWAPIEnabledWorker.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWAPIEnabledWorker.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 07/10/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | 16 | extern NSString *SWAXAPIEnabledKey; 17 | 18 | 19 | @interface SWAPIEnabledWorker : NNPollingObject 20 | 21 | + (BOOL)isAPIEnabled; 22 | 23 | - (instancetype)init; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Switch/SWAPIEnabledWorker.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWAPIEnabledWorker.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 07/10/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | #import "SWAPIEnabledWorker.h" 15 | 16 | #import 17 | #import 18 | 19 | 20 | NSString *SWAXAPIEnabledKey = @"AXAPIEnabled"; 21 | 22 | 23 | @interface SWAPIEnabledWorker () 24 | 25 | @property (nonatomic, assign, readwrite) BOOL APIEnabled; 26 | 27 | @end 28 | 29 | 30 | @implementation SWAPIEnabledWorker 31 | 32 | #pragma mark - Initialization 33 | 34 | - (instancetype)init; 35 | { 36 | if (!(self = [super initWithQueue:dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)])) { return nil; } 37 | 38 | _APIEnabled = [[self class] isAPIEnabled]; 39 | self.interval = 0.25; 40 | 41 | return self; 42 | } 43 | 44 | #pragma mark - NNPollingObject 45 | 46 | - (void)main; 47 | { 48 | BOOL enabled = [[self class] isAPIEnabled]; 49 | if (enabled != self.APIEnabled) { 50 | self.APIEnabled = enabled; 51 | [self postNotification:@{ SWAXAPIEnabledKey : @(enabled) }]; 52 | } 53 | } 54 | 55 | #pragma mark - SWAPIEnabledWorker 56 | 57 | + (BOOL)isAPIEnabled; 58 | { 59 | return (BOOL)AXIsProcessTrustedWithOptions(nil); 60 | } 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Switch/SWAccessibilityService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWAccessibilityService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/20/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @class SWWindow; 16 | 17 | 18 | @interface SWAccessibilityService : NNService 19 | 20 | - (void)checkAPI; 21 | 22 | - (void)raiseWindow:(SWWindow *)window completion:(void(^)(NSError *))completionBlock; 23 | - (void)closeWindow:(SWWindow *)window completion:(void(^)(NSError *))completionBlock; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Switch/SWAdvancedPreferencesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWAdvancedPreferencesViewController.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/30/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "MASPreferencesViewController.h" 16 | 17 | 18 | @interface SWAdvancedPreferencesViewController : NSViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Switch/SWAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWAppDelegate.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/24/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWAppDelegate : NSObject 19 | 20 | - (void)relaunch:(id)sender; 21 | - (IBAction)showPreferences:(id)sender; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Switch/SWApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWApplication.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/21/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWApplication : NSObject 19 | 20 | + (instancetype)applicationWithPID:(pid_t)pid name:(NSString *)name; 21 | 22 | @property (nonatomic, assign, readonly) pid_t pid; 23 | @property (nonatomic, copy, readonly) NSImage *cachedIcon; 24 | @property (nonatomic, strong, readonly) NSString *name; 25 | 26 | - (NSImage *)loadIcon; 27 | 28 | - (BOOL)isActiveApplication; 29 | - (BOOL)isLiveApplication; 30 | - (BOOL)canBeActivated; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Switch/SWCoreWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWCoreWindowController.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 07/10/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class SWCoreWindowController; 19 | @class SWWindow; 20 | 21 | 22 | @protocol SWCoreWindowControllerDelegate 23 | 24 | - (void)coreWindowController:(SWCoreWindowController *)controller didSelectWindow:(SWWindow *)window; 25 | - (void)coreWindowController:(SWCoreWindowController *)controller didActivateWindow:(SWWindow *)window; 26 | - (void)coreWindowControllerDidClickOutsideInterface:(SWCoreWindowController *)controller; 27 | 28 | @end 29 | 30 | 31 | // A poor attempt at getting core window controllers to be well-behaved targets for the multi-dispatch manager. 32 | @protocol SWCoreWindowControllerAPI 33 | 34 | @required 35 | - (void)updateWindowList:(NSOrderedSet *)windowList; 36 | - (void)selectWindow:(SWWindow *)window; 37 | - (void)disableWindow:(SWWindow *)window; 38 | - (void)enableWindow:(SWWindow *)window; 39 | 40 | @end 41 | 42 | 43 | @interface SWCoreWindowController : NSWindowController 44 | 45 | @property (nonatomic, strong, setter=updateWindowList:) NSOrderedSet *windowList; 46 | @property (nonatomic, weak) id delegate; 47 | 48 | - (id)initWithScreen:(NSScreen *)screen; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /Switch/SWCoreWindowService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWCoreWindowService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 11/19/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @interface SWCoreWindowService : NNService 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Switch/SWEventTap.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWEventTap.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/13/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWHotKey.h" 16 | 17 | 18 | typedef BOOL (^SWEventTapKeyFilter)(CGEventRef event); 19 | typedef void (^SWEventTapModifierCallback)(BOOL matched); 20 | typedef void (^SWEventTapCallback)(CGEventRef event); 21 | 22 | 23 | @interface SWEventTap : NNService 24 | 25 | @property (nonatomic, assign, readwrite) BOOL suppressKeyEvents; 26 | 27 | // For key bindings. Block can return NO to stop the event's further propagation. 28 | - (void)registerHotKey:(SWHotKey *)hotKey object:(id)owner block:(SWEventTapKeyFilter)eventFilter; 29 | - (void)removeBlockForHotKey:(SWHotKey *)hotKey object:(id)owner; 30 | 31 | // For modifier key state updates. Used to dismiss the interface. 32 | - (void)registerModifier:(SWHotKeyModifierKey)modifiers object:(id)owner block:(SWEventTapModifierCallback)eventCallback; 33 | - (void)removeBlockForModifier:(SWHotKeyModifierKey)modifiers object:(id)owner; 34 | 35 | // Primarily for mouse move and scroll events. Used for selector updates.. 36 | - (void)registerForEventsWithType:(CGEventType)eventType object:(id)owner block:(SWEventTapCallback)eventCallback; 37 | - (void)removeBlockForEventsWithType:(CGEventType)eventType object:(id)owner; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Switch/SWGeneralPreferencesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWGeneralPreferencesViewController.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/10/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "MASPreferencesViewController.h" 16 | 17 | 18 | @interface SWGeneralPreferencesViewController : NSViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Switch/SWHUDCollectionView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWHUDCollectionView.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 05/28/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @protocol SWHUDCollectionViewDataSource; 16 | @protocol SWHUDCollectionViewDelegate; 17 | 18 | 19 | @interface SWHUDCollectionView : NSView 20 | 21 | @property (nonatomic, weak) id dataSource; 22 | @property (nonatomic, weak) id delegate; 23 | 24 | @property (nonatomic, readonly) NSUInteger selectedIndex; 25 | 26 | - (NSUInteger)numberOfCells; 27 | 28 | - (NSView *)cellForIndex:(NSUInteger)index; 29 | 30 | - (void)selectCellAtIndex:(NSUInteger)index; 31 | - (void)deselectCell; 32 | 33 | - (void)reloadData; 34 | 35 | @end 36 | 37 | 38 | @protocol SWHUDCollectionViewDataSource 39 | 40 | - (CGFloat)HUDCollectionViewMaximumCellSize:(SWHUDCollectionView *)view; 41 | - (NSUInteger)HUDCollectionViewNumberOfCells:(SWHUDCollectionView *)view; 42 | - (NSView *)HUDCollectionView:(SWHUDCollectionView *)view viewForCellAtIndex:(NSUInteger)index; 43 | 44 | @end 45 | 46 | 47 | @protocol SWHUDCollectionViewDelegate 48 | 49 | @optional 50 | - (void)HUDCollectionView:(SWHUDCollectionView *)view willSelectCellAtIndex:(NSUInteger)index; 51 | - (void)HUDCollectionView:(SWHUDCollectionView *)view didSelectCellAtIndex:(NSUInteger)index; 52 | - (void)HUDCollectionView:(SWHUDCollectionView *)view activateCellAtIndex:(NSUInteger)index; 53 | - (void)HUDCollectionViewClickOutsideCollection:(SWHUDCollectionView *)view; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Switch/SWHUDView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWHUDView.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/02/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWRoundedRectView.h" 16 | 17 | 18 | @interface SWHUDView : SWRoundedRectView 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Switch/SWHUDView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWHUDView.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/02/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWHUDView.h" 16 | 17 | 18 | @implementation SWHUDView 19 | 20 | #pragma mark - Initialization 21 | 22 | - (id)initWithFrame:(CGRect)frame 23 | { 24 | BailUnless(self = [super initWithFrame:frame], nil); 25 | 26 | self.border = 0.0; 27 | self.radius = kNNWindowRoundRectRadius; 28 | self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Switch/SWHotKey.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWHotKey.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 07/16/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | #import 17 | 18 | 19 | typedef NS_OPTIONS(unsigned, SWHotKeyModifierKey) { 20 | SWHotKeyModifierShift = controlKey, 21 | SWHotKeyModifierOption = optionKey, 22 | SWHotKeyModifierControl = shiftKey, 23 | SWHotKeyModifierCmd = cmdKey, 24 | }; 25 | 26 | 27 | @interface SWHotKey : NSObject 28 | 29 | @property (nonatomic, readonly) CGKeyCode code; 30 | @property (nonatomic, readonly) SWHotKeyModifierKey modifiers; 31 | 32 | + (SWHotKey *)hotKeyWithKeycode:(CGKeyCode)code modifiers:(SWHotKeyModifierKey)modifiers; 33 | + (SWHotKey *)hotKeyFromEvent:(CGEventRef)event; 34 | 35 | - (NSString *)modifierDescription; 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /Switch/SWInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWInterfaceController.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/01/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class SWInterfaceController; 19 | @class SWWindow; 20 | 21 | 22 | @protocol SWInterfaceControllerDelegate 23 | 24 | - (void)interfaceController:(SWInterfaceController *)controller didSelectWindow:(SWWindow *)window; 25 | - (void)interfaceController:(SWInterfaceController *)controller didActivateWindow:(SWWindow *)window; 26 | - (void)interfaceControllerDidClickOutsideInterface:(SWInterfaceController *)controller; 27 | 28 | @end 29 | 30 | 31 | @interface SWInterfaceController : NSObject 32 | 33 | @property (nonatomic, readwrite, assign, getter=showingInterface, setter=shouldShowInterface:) _Bool showInterface; 34 | 35 | - (instancetype)initWithDelegate:(id)delegate; 36 | 37 | - (void)updateWindowList:(NSOrderedSet *)windowList; 38 | - (void)selectWindow:(SWWindow *)window; 39 | - (void)disableWindow:(SWWindow *)window; 40 | - (void)enableWindow:(SWWindow *)window; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Switch/SWKeyboardPreferencesViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWKeyboardPreferencesViewController.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/28/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWKeyboardPreferencesViewController : NSViewController 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Switch/SWKeyboardPreferencesViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWKeyboardPreferencesViewController.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/28/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWKeyboardPreferencesViewController.h" 16 | 17 | 18 | @interface SWKeyboardPreferencesViewController () 19 | 20 | @end 21 | 22 | 23 | @implementation SWKeyboardPreferencesViewController 24 | 25 | #pragma mark - MASPreferencesViewController 26 | 27 | - (NSString *)identifier 28 | { 29 | return NSStringFromClass([self class]); 30 | } 31 | 32 | - (NSImage *)toolbarItemImage 33 | { 34 | return [NSImage imageNamed:@"Keyboard.icns"]; 35 | } 36 | 37 | - (NSString *)toolbarItemLabel 38 | { 39 | return NSLocalizedString(@"Hotkeys", @"Toolbar item name for the Hotkeys preference pane"); 40 | } 41 | 42 | - (BOOL)hasResizableWidth; 43 | { 44 | return NO; 45 | } 46 | 47 | - (BOOL)hasResizableHeight; 48 | { 49 | return NO; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Switch/SWLoggingService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWLoggingService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/15/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWLoggingService : NNService 19 | 20 | - (NSString *)logDirectoryPath; 21 | - (void)rotateLogIfNecessary; 22 | - (void)takeWindowListSnapshot; 23 | 24 | @end 25 | 26 | #define SWLog(fmt, ...) do { \ 27 | [[SWLoggingService sharedService] rotateLogIfNecessary]; \ 28 | Log(fmt, ##__VA_ARGS__); \ 29 | } while(0) 30 | 31 | #define SWLogBackgroundThreadOnly() do { \ 32 | if ([NSThread isMainThread]) { \ 33 | SWLog(@"ERROR: -[%@ %@] was called on the main thread %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [NSThread callStackSymbols]); \ 34 | Assert(![NSThread isMainThread]); \ 35 | } \ 36 | } while(0) 37 | 38 | #define SWLogMainThreadOnly() do { \ 39 | if (![NSThread isMainThread]) { \ 40 | SWLog(@"ERROR: -[%@ %@] was called on a background thread %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), [NSThread callStackSymbols]); \ 41 | Assert([NSThread isMainThread]); \ 42 | } \ 43 | } while(0) 44 | 45 | #define SWCodeBlock(...) __VA_ARGS__ 46 | 47 | #define SWTimeTask(codeBlock, fmt, ...) do { \ 48 | NSDate *start = [NSDate new]; \ 49 | codeBlock \ 50 | NSString *logmsg = [NSString stringWithFormat:fmt, ##__VA_ARGS__]; \ 51 | NSTimeInterval elapsed = -[start timeIntervalSinceNow]; \ 52 | if (elapsed > (1.0 / ([NSThread isMainThread] ? 60.0 : 10.0))) { \ 53 | SWLog(@"%@ took %.3fs", logmsg, elapsed); \ 54 | } \ 55 | } while(0) 56 | -------------------------------------------------------------------------------- /Switch/SWPreferencesService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWPreferencesService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/20/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class SWPreferencesService; 19 | 20 | 21 | @interface SWPreferencesService : NNService 22 | 23 | @property (nonatomic, assign, readwrite) _Bool multimonInterface; 24 | @property (nonatomic, assign, readwrite) _Bool multimonGroupByMonitor; 25 | @property (nonatomic, assign, readwrite) _Bool showStatusItem; 26 | @property (nonatomic, strong, readwrite, null_resettable) NSString *appcastURL; 27 | 28 | - (void)showPreferencesWindow:(nonnull id)sender; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Switch/SWRoundedRectView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWRoundedRectView.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/01/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWRoundedRectView : NSView 19 | 20 | @property (nonatomic, assign) CGFloat border; 21 | @property (nonatomic, assign) CGFloat radius; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Switch/SWRoundedRectView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWRoundedRectView.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/01/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWRoundedRectView.h" 16 | 17 | 18 | @implementation SWRoundedRectView 19 | 20 | #pragma mark - Initialization 21 | 22 | - (instancetype)initWithFrame:(CGRect)frame; 23 | { 24 | BailUnless(self = [super initWithFrame:frame], nil); 25 | 26 | [self setWantsLayer:YES]; 27 | 28 | return self; 29 | } 30 | 31 | #pragma mark - NSView 32 | 33 | - (void)updateLayer; 34 | { 35 | if (self.border > 0) { 36 | self.layer.borderWidth = self.border; 37 | self.layer.borderColor = [[[NSColor whiteColor] colorWithAlphaComponent:0.8] CGColor]; 38 | } 39 | 40 | self.layer.cornerRadius = self.radius; 41 | self.layer.backgroundColor = [[[NSColor blackColor] colorWithAlphaComponent:0.3] CGColor]; 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Switch/SWScrollControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWScrollControl.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 09/30/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @interface SWScrollControl : NSObject 19 | 20 | - (instancetype)initWithThreshold:(NSInteger)threshold incHandler:(dispatch_block_t)incBlock decHandler:(dispatch_block_t)decBlock; 21 | 22 | - (void)feed:(NSInteger)numEvents; 23 | - (void)reset; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Switch/SWScrollControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWScrollControl.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 09/30/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWScrollControl.h" 16 | 17 | 18 | static NSInteger const kMaxThreshold = NSIntegerMax / 2; 19 | 20 | 21 | @interface SWScrollControl () 22 | 23 | @property (nonatomic, readonly, strong) dispatch_block_t inc; 24 | @property (nonatomic, readonly, strong) dispatch_block_t dec; 25 | @property (nonatomic, readonly, assign) NSInteger threshold; 26 | @property (nonatomic, readwrite, assign) NSInteger offset; 27 | 28 | @end 29 | 30 | 31 | @implementation SWScrollControl 32 | 33 | - (instancetype)initWithThreshold:(NSInteger)threshold incHandler:(dispatch_block_t)incBlock decHandler:(dispatch_block_t)decBlock; 34 | { 35 | BailUnless(self = [super init], nil); 36 | 37 | self->_inc = incBlock; 38 | self->_dec = decBlock; 39 | self->_threshold = labs(threshold); 40 | 41 | if (self->_threshold > kMaxThreshold) { 42 | NSLog(@"%@ does not support thresholds larger than %ld", NSStringFromClass([self class]), kMaxThreshold); 43 | return nil; 44 | } 45 | 46 | return self; 47 | } 48 | 49 | - (void)feed:(NSInteger)numEvents; 50 | { 51 | NSInteger units = (numEvents / self.threshold); 52 | numEvents %= self.threshold; 53 | 54 | self.offset += numEvents; 55 | 56 | units += (self.offset / self.threshold); 57 | self.offset %= self.threshold; 58 | 59 | while (units > 0) { 60 | self.inc(); 61 | units--; 62 | } 63 | while (units < 0) { 64 | self.dec(); 65 | units++; 66 | } 67 | } 68 | 69 | - (void)reset; 70 | { 71 | self.offset = 0; 72 | } 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Switch/SWSelectionBoxView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWSelectionBoxView.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/02/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWRoundedRectView.h" 16 | 17 | 18 | @interface SWSelectionBoxView : SWRoundedRectView 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Switch/SWSelectionBoxView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWSelectionBoxView.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/02/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWSelectionBoxView.h" 16 | 17 | 18 | @implementation SWSelectionBoxView 19 | 20 | #pragma mark - Initialization 21 | 22 | - (id)initWithFrame:(CGRect)frame 23 | { 24 | BailUnless(self = [super initWithFrame:frame], nil); 25 | 26 | self.border = kNNItemBorderWidth; 27 | self.radius = kNNSelectionRoundRectRadius; 28 | self.translatesAutoresizingMaskIntoConstraints = NO; 29 | 30 | return self; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Switch/SWSelector.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWSelector.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/05/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class SWWindow; 19 | 20 | 21 | @interface SWSelector : NSObject 22 | 23 | @property (nonatomic, copy, readonly) SWWindow *selectedWindow; 24 | @property (nonatomic, assign, readonly) NSInteger selectedIndex; 25 | @property (nonatomic, copy, readonly) NSOrderedSet *windowList; 26 | 27 | - (NSUInteger)selectedUIndex; 28 | 29 | - (instancetype)increment; 30 | - (instancetype)incrementWithoutWrapping; 31 | - (instancetype)decrement; 32 | - (instancetype)decrementWithoutWrapping; 33 | - (instancetype)selectIndex:(NSInteger)index; 34 | - (instancetype)updateWithWindowList:(NSOrderedSet *)windowList; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Switch/SWStatusBarMenuService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWStatusBarMenuService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/15/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface SWStatusBarMenuService : NNService 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Switch/SWWindow+TweetbotQuirks.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindow+TweetBotQuirks.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/11/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindow.h" 16 | 17 | @interface SWWindow (TweetbotQuirks) 18 | 19 | - (BOOL)tweetbot_isRelatedToLowerWindow:(SWWindow *)window; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Switch/SWWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindow.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/21/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | typedef NSPoint NNVec2; 19 | 20 | 21 | @class SWApplication; 22 | 23 | 24 | @interface SWWindow : NSObject 25 | 26 | + (instancetype)windowWithDescription:(NSDictionary *)description; 27 | 28 | @property (nonatomic, strong, readonly) SWApplication *application; 29 | @property (atomic, copy, readonly) NSDictionary *windowDescription; 30 | 31 | - (CGRect)frame; 32 | - (CGRect)flippedFrame; 33 | - (NSString *)name; 34 | - (NSScreen *)screen; 35 | - (CGWindowID)windowID; 36 | 37 | - (NSString *)displayName; 38 | 39 | - (BOOL)isSameWindow:(SWWindow *)window; 40 | - (BOOL)isRelatedToLowerWindow:(SWWindow *)window; 41 | - (NNVec2)offsetOfCenterToCenterOfWindow:(SWWindow *)window; 42 | - (NSSize)sizeDifferenceFromWindow:(SWWindow *)window; 43 | - (BOOL)enclosedByWindow:(SWWindow *)window; 44 | 45 | @end 46 | -------------------------------------------------------------------------------- /Switch/SWWindowContentsService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowContentsService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/02/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @class SWWindow; 16 | @class SWWindowContentsService; 17 | 18 | 19 | @protocol SWWindowContentsSubscriber 20 | 21 | - (oneway void)windowContentService:(SWWindowContentsService *)windowService updatedContent:(NSImage *)content forWindow:(SWWindow *)window; 22 | 23 | @end 24 | 25 | 26 | @interface SWWindowContentsService : NNService 27 | 28 | - (NSImage *)contentForWindow:(SWWindow *)window; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Switch/SWWindowGroup.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowGroup.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 12/24/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindow.h" 16 | 17 | 18 | @class SWApplication; 19 | 20 | 21 | @interface SWWindowGroup : SWWindow 22 | 23 | @property (nonatomic, strong, readonly) SWWindow *mainWindow; 24 | @property (nonatomic, strong, readonly) NSOrderedSet *windows; 25 | 26 | - (instancetype)initWithWindows:(NSOrderedSet *)windows mainWindow:(SWWindow *)mainWindow; 27 | 28 | - (BOOL)isRelatedToLowerGroup:(SWWindowGroup *)group; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Switch/SWWindowListService.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowListService.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 12/24/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @class SWWindowListService; 16 | 17 | 18 | @protocol SWWindowListSubscriber 19 | @optional 20 | 21 | - (oneway void)windowListServiceStarted:(SWWindowListService *)service; 22 | - (oneway void)windowListService:(SWWindowListService *)service updatedList:(NSOrderedSet *)windows; 23 | - (oneway void)windowListServiceStopped:(SWWindowListService *)service; 24 | 25 | @end 26 | 27 | 28 | @interface SWWindowListService : NNService 29 | 30 | + (NSOrderedSet *)filterInfoDictionariesToWindowObjects:(NSArray *)infoDicts; 31 | + (NSOrderedSet *)filterWindowObjectsToWindowGroups:(NSOrderedSet *)rawWindowList; 32 | + (NSOrderedSet *)sortedWindowGroups:(NSOrderedSet *)windowGroups; 33 | 34 | @property (nonatomic, copy, readonly) NSOrderedSet *windows; 35 | 36 | // Background threads only! 37 | - (void)refreshWindowListAndWait; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Switch/SWWindowListWorker.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowListWorker.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/22/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @interface SWWindowListWorker : NNPollingObject 16 | 17 | - (void)refreshWindowListAndWait; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Switch/SWWindowListWorker.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowListWorker.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/22/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListWorker.h" 16 | 17 | #import 18 | 19 | 20 | static NSTimeInterval refreshInterval = 0.1; 21 | 22 | 23 | @interface SWWindowListWorker () 24 | 25 | @property (nonatomic, copy, readwrite) NSArray *windowInfoList; 26 | @property (nonatomic, strong) dispatch_queue_t private_queue; 27 | 28 | @end 29 | 30 | 31 | @implementation SWWindowListWorker 32 | 33 | #pragma mark - Initialization 34 | 35 | - (instancetype)init; 36 | { 37 | dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 38 | if (!(self = [super initWithQueue:q])) { return nil; } 39 | 40 | self.private_queue = q; 41 | self.interval = refreshInterval; 42 | 43 | return self; 44 | } 45 | 46 | #pragma mark - NNPollingObject 47 | 48 | - (oneway void)main; 49 | { 50 | [self private_refreshWindowList]; 51 | } 52 | 53 | #pragma mark - SWWindowListWorker 54 | 55 | - (void)refreshWindowListAndWait; 56 | { 57 | dispatch_sync(self.private_queue, ^{ 58 | [self private_refreshWindowList]; 59 | }); 60 | } 61 | 62 | - (void)private_refreshWindowList; 63 | { 64 | SWLogBackgroundThreadOnly(); 65 | 66 | SWTimeTask(SWCodeBlock({ 67 | CFArrayRef cgWindowInfoList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID); 68 | NSArray *windowInfoList = CFBridgingRelease(cgWindowInfoList); 69 | if (![self.windowInfoList isEqualToArray:windowInfoList]) { 70 | self.windowInfoList = windowInfoList; 71 | [self postNotification:@{@"windows" : self.windowInfoList}]; 72 | } 73 | }), @"Copying window info list"); 74 | } 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /Switch/SWWindowThumbnailView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowThumbnailView.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/21/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | @class SWWindow; 19 | 20 | 21 | @interface SWWindowThumbnailView : NSView 22 | 23 | - (instancetype)initWithFrame:(CGRect)frameRect window:(SWWindow *)window; 24 | 25 | - (void)setActive:(BOOL)active; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Switch/SWWindowWorker.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowWorker.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/22/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | @class SWWindow; 16 | 17 | 18 | @interface SWWindowWorker : NNPollingObject 19 | 20 | - (instancetype)initWithModelObject:(SWWindow *)window __attribute__((nonnull(1))); 21 | 22 | - (CGWindowID) windowID; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Switch/Sparkle.dsa_pub.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PUBLIC KEY----- 2 | MIIDOjCCAi0GByqGSM44BAEwggIgAoIBAQCRka+uAlcerqIXNFJuII/YNdl5qB8c 3 | QGDYct1OhPpRKuQquy6imYtFl1ZRv8DOLnVZQFQYd1t/a6/thwc/Nl3M1h8p3dvx 4 | 5CD6lN7ph0rMBO+r5b3SQp6HVZtRf7c7tGweHkBtv4TkLYYBXgUcse9IdB9deZZ5 5 | KofWYNS7FPXWnpqYDvu/cQ2e+SjRdvydJui6YpZMhGuY4sIMjLFhqKrnIwL8Lk7e 6 | zrDofhhLri4WqsspMis4tcTObG/RKRJ3lQ9Ao0D4Wsak9wiaPcml4/OnbF7ivr3p 7 | HIXW+WDKI0QcL94UjM5K8CQ2pdD+Xkprcn3iEY+vopTLvyv5+1l7pX7DAhUA/dqJ 8 | 5WIBtx3fZz2U24ngdmtg9BUCggEADRDOa+Sta0EnVvOwZwzDBIUoelX6BYDj1qrP 9 | khQYOlh1gJdTCmSSuMPdh651djOJZivYgdvyOdV+Wq5cI8WSn7UU1qqhw3qnyjYK 10 | u74OPBH5YM7KALRkrVoJkCdKi6voWLxMBo9HVKs2ima6fatJk3ZpuxdQZrFMVayP 11 | xTOubvwlncNTU/WCpA8zshIdgw+Y95Zoxfu78gNRYMg9f14znIAzpYkxasnIvHGx 12 | BWhYegzopIvf5GBs+6V6tzIt9JCSpeyBaq9htvO6PkEtbITJHTvtJRK6O6wZHibU 13 | U5U1jKYmKap6CbDccHGelXOE/j7lXVdFe0p31zrUwmX+hT07tAOCAQUAAoIBACeq 14 | dDhGkZN/IhQI10f5AzlS+5KtoDPgCK9jAQF9eeqoNA+gtbkPsa9b0LH8Dfu8hgwA 15 | Liu3cHTaocfuRNhlBeUAgfBTs50rZlESk3QnDYqBPLUcopQHKgD+JYoSzsJsXsrd 16 | R2SnYtaHb8UivU9nYmi8jB58RrouqSrqOmn3YTbbQILRn4tTbn6yN5H5DOl3C99B 17 | riCx+OMeG/3aLo03vbAdXc0IL2Jr1+XOgXaHQyuZKxytl7yM5taUd4T/a16924jj 18 | 8vISK+2SN9GK2k9jWo5bWC07DO2sfO2ge8sJFDepl9REi/DMiFlzNKfqwfmJTs59 19 | aSzo181mAiCIc6G70sk= 20 | -----END PUBLIC KEY----- 21 | -------------------------------------------------------------------------------- /Switch/Switch-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | 5 | -------------------------------------------------------------------------------- /Switch/Switch-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSAppleEventsUsageDescription 6 | 7 | LSUIElement 8 | 9 | CFBundleDevelopmentRegion 10 | en 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIconFile 14 | 15 | CFBundleIdentifier 16 | net.numist.${PRODUCT_NAME:rfc1034identifier} 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 0.0.10 (β) 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 0.0.10 29 | LSApplicationCategoryType 30 | public.app-category.productivity 31 | LSMinimumSystemVersion 32 | ${MACOSX_DEPLOYMENT_TARGET} 33 | NSHumanReadableCopyright 34 | Copyright © 2016 Scott Perry. 35 | 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: 36 | 37 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 38 | 39 | 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. 40 | NSMainNibFile 41 | MainMenu 42 | NSPrincipalClass 43 | NSApplication 44 | SUEnableAutomaticChecks 45 | 46 | SUShowReleaseNotes 47 | 48 | SUPublicDSAKeyFile 49 | Sparkle.dsa_pub.pem 50 | 51 | 52 | -------------------------------------------------------------------------------- /Switch/Switch-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Switch' target in the 'Switch' project 3 | // 4 | 5 | #define Log(fmt, ...) do { \ 6 | NSLog(@"%@:%d %@", [[[NSString alloc] initWithCString:(__FILE__) encoding:NSUTF8StringEncoding] lastPathComponent], __LINE__, [NSString stringWithFormat:(fmt), ##__VA_ARGS__]); \ 7 | } while(0) 8 | 9 | #ifdef __OBJC__ 10 | # import 11 | # import 12 | # import 13 | # import 14 | # import "debugger.h" 15 | # import "constants.h" 16 | # import "helpers.h" 17 | # import "SWLoggingService.h" 18 | #endif 19 | 20 | #define sw_deprecated __attribute__((deprecated)) 21 | #define sw_unused __attribute__((unused)) 22 | -------------------------------------------------------------------------------- /Switch/Switch.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Switch/constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // constants.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/01/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | // Points 19 | extern const CGFloat kNNMaxWindowThumbnailSize; 20 | extern const CGFloat kNNMaxApplicationIconSize; 21 | extern const CGFloat kNNScreenToWindowInset; 22 | extern const CGFloat kNNWindowToItemInset; 23 | extern const CGFloat kNNItemBorderWidth; 24 | extern const CGFloat kNNItemToThumbInset; 25 | extern const CGFloat kNNWindowToThumbInset; 26 | extern const CGFloat kNNWindowRoundRectRadius; 27 | extern const CGFloat kNNSelectionRoundRectRadius; 28 | 29 | // Seconds 30 | extern const NSTimeInterval delayBeforePresentingSwitcherWindow; 31 | 32 | // Enum stringification 33 | NSString *NNStringFromCGWindowLevel(long level); 34 | 35 | // Helper macros 36 | #define CLASS_CAST(Classname, value) ((Classname *)CLASS_CAST_IMPL([Classname class], (value))) 37 | id CLASS_CAST_IMPL(Class class, id value); 38 | -------------------------------------------------------------------------------- /Switch/debugger.c: -------------------------------------------------------------------------------- 1 | // 2 | // debugger.c 3 | // Debugger 4 | // 5 | // Created by Scott Perry on 8/11/11. 6 | // Public domain. 7 | // 8 | 9 | #if defined(DEBUG) 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | /* 18 | * NOTE: Forward decl of AmIBeingDebugged since this file is built without platform flags 19 | * (resulting in a warning when including debugger.h directly) 20 | */ 21 | bool AmIBeingDebugged(void); 22 | 23 | /* 24 | * This function provided by Apple TechNote QA1361: 25 | * http://developer.apple.com/library/mac/#qa/qa1361/_index.html 26 | */ 27 | bool AmIBeingDebugged(void) 28 | // Returns true if the current process is being debugged (either 29 | // running under the debugger or has a debugger attached post facto). 30 | { 31 | int junk; 32 | int mib[4]; 33 | struct kinfo_proc info; 34 | size_t size; 35 | 36 | // Initialize the flags so that, if sysctl fails for some bizarre 37 | // reason, we get a predictable result. 38 | 39 | info.kp_proc.p_flag = 0; 40 | 41 | // Initialize mib, which tells sysctl the info we want, in this case 42 | // we're looking for information about a specific process ID. 43 | 44 | mib[0] = CTL_KERN; 45 | mib[1] = KERN_PROC; 46 | mib[2] = KERN_PROC_PID; 47 | mib[3] = getpid(); 48 | 49 | // Call sysctl. 50 | 51 | size = sizeof(info); 52 | junk = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); 53 | assert(junk == 0); 54 | 55 | // We're being debugged if the P_TRACED flag is set. 56 | 57 | return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 58 | } 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /Switch/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf370 2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | \vieww9600\viewh8400\viewkind0 5 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720 6 | 7 | \f0\b\fs24 \cf0 Engineering: 8 | \b0 \ 9 | Scott Perry\ 10 | \ 11 | 12 | \b Human Interface Design: 13 | \b0 \ 14 | Nobody\ 15 | \ 16 | 17 | \b Testing: 18 | \b0 \ 19 | So far, nobody\ 20 | \ 21 | 22 | \b Documentation: 23 | \b0 \ 24 | Oops\ 25 | \ 26 | 27 | \b With special thanks to: 28 | \b0 \ 29 | David Smith, Gwynne Raskind, and Rob Rix\ 30 | } -------------------------------------------------------------------------------- /Switch/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Switch/helpers.h: -------------------------------------------------------------------------------- 1 | // 2 | // helpers.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | 18 | #define NNAssertMainQueue() NSAssert([[NSThread currentThread] isMainThread], @"Current path of execution must be run on the main thread"); 19 | 20 | BOOL NNCGRectsEqual(CGRect a, CGRect b); 21 | BOOL NNNSSizesEqual(NSSize a, NSSize b); 22 | 23 | void *NNCFAutorelease(CFTypeRef cfObject); 24 | -------------------------------------------------------------------------------- /Switch/helpers.m: -------------------------------------------------------------------------------- 1 | // 2 | // helpers.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "helpers.h" 16 | 17 | 18 | BOOL NNNSSizesEqual(NSSize a, NSSize b) 19 | { 20 | return a.width == b.width && a.height == b.height; 21 | } 22 | 23 | BOOL NNCGRectsEqual(CGRect a, CGRect b) 24 | { 25 | return a.origin.x == b.origin.x && a.origin.y == b.origin.y && NNNSSizesEqual(a.size, b.size); 26 | } 27 | 28 | void *NNCFAutorelease(CFTypeRef cfObject) 29 | { 30 | if (cfObject) { 31 | static Class arp = Nil; 32 | static dispatch_once_t onceToken; 33 | dispatch_once(&onceToken, ^{ 34 | arp = NSClassFromString(@"NSAutoreleasePool"); 35 | Assert(arp); 36 | }); 37 | 38 | [arp addObject:(__bridge id)cfObject]; 39 | } 40 | 41 | return (void *)cfObject; 42 | } 43 | -------------------------------------------------------------------------------- /Switch/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 02/24/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | int main(int argc, char *argv[]) 18 | { 19 | return NSApplicationMain(argc, (const char **)argv); 20 | } 21 | -------------------------------------------------------------------------------- /SwitchTests/NSImage+NNFilesystem.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+NNFilesystem.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface NSImage (NNFilesystem) 18 | 19 | - (BOOL)writeTIFFToFile:(NSString *)path; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SwitchTests/NSImage+NNFilesystem.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+NNFilesystem.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSImage+NNFilesystem.h" 16 | 17 | @implementation NSImage (NNFilesystem) 18 | 19 | - (BOOL)writeTIFFToFile:(NSString *)path; 20 | { 21 | return [[self TIFFRepresentation] writeToFile:path atomically:NO]; 22 | } 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SwitchTests/NSWindow+NNScreenCapture.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSWindow+NNScreenCapture.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | @interface NSWindow (NNScreenCapture) 18 | 19 | - (NSImage *)nnImage; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /SwitchTests/NSWindow+NNScreenCapture.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSWindow+NNScreenCapture.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "NSWindow+NNScreenCapture.h" 16 | 17 | @implementation NSWindow (NNScreenCapture) 18 | 19 | - (NSImage *)nnImage; 20 | { 21 | CGWindowID windowID = (CGWindowID)self.windowNumber; 22 | CGImageRef cgShot = CGWindowListCreateImage(CGRectNull, kCGWindowListOptionIncludingWindow, windowID, kCGWindowImageDefault); 23 | Check(cgShot); 24 | NSImage *nsShot = [[NSImage alloc] initWithCGImage:cgShot size:NSZeroSize]; 25 | 26 | CFRelease(cgShot); 27 | cgShot = NULL; 28 | 29 | return nsShot; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /SwitchTests/References/image.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/SwitchTests/References/image.tiff -------------------------------------------------------------------------------- /SwitchTests/SWDashTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWDashTests.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/05/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListServiceTestSuperclass.h" 16 | 17 | 18 | @interface SWDashTests : SWWindowListServiceTestSuperclass 19 | 20 | @end 21 | 22 | 23 | @implementation SWDashTests 24 | 25 | // https://github.com/numist/Switch/issues/48 26 | - (void)testUnnamedDashWindow; 27 | { 28 | NSDictionary *windowDescription = @{ 29 | NNWindowAlpha : @1, 30 | NNWindowBounds : DICT_FROM_RECT(((CGRect){ 31 | .size.height = 616, 32 | .size.width = 936, 33 | .origin.x = 44, 34 | .origin.y = 36 35 | })), 36 | NNWindowIsOnscreen : @1, 37 | NNWindowLayer : @0, 38 | NNWindowMemoryUsage : @2576052, 39 | NNWindowNumber : @84004, 40 | NNWindowOwnerName : @"Dash", 41 | NNWindowOwnerPID : @7852, 42 | NNWindowSharingState : @1, 43 | NNWindowStoreType : @2, 44 | }; 45 | NSArray *infoList = @[windowDescription]; 46 | 47 | [self updateListServiceWithInfoList:infoList]; 48 | XCTAssertEqual(self.listService.windows.count, 1, @"Dash was incorrectly filtered out"); 49 | XCTAssertEqual(((SWWindowGroup *)[self.listService.windows objectAtIndex:0]).windows.count, infoList.count, @""); 50 | XCTAssertEqualObjects(((SWWindowGroup *)[self.listService.windows objectAtIndex:0]).mainWindow.windowDescription, windowDescription, @""); 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /SwitchTests/SWFinderTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWFinderTests.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 05/13/16. 6 | // Copyright © 2016 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListServiceTestSuperclass.h" 16 | 17 | 18 | @interface SWFinderTests : SWWindowListServiceTestSuperclass 19 | 20 | @end 21 | 22 | 23 | @implementation SWFinderTests 24 | 25 | - (void)testQuicklookWindow; 26 | { 27 | // This Quicklook window was recorded on OS X 10.11.3 when Finder was not frontmost 28 | NSArray *infoList = @[ 29 | @{ 30 | NNWindowLayer : @0, 31 | NNWindowAlpha : @1.000000, 32 | NNWindowMemoryUsage : @1024, 33 | NNWindowIsOnscreen : @1, 34 | NNWindowSharingState : @1, 35 | NNWindowOwnerPID : @58213, 36 | NNWindowNumber : @14164, 37 | NNWindowOwnerName : @"Finder", 38 | NNWindowStoreType : @1, 39 | NNWindowBounds : @{ 40 | @"Height" : @669, 41 | @"Width" : @366, 42 | @"X" : @500, 43 | @"Y" : @59, 44 | }, 45 | NNWindowName : @"", 46 | }, 47 | ]; 48 | 49 | [self updateListServiceWithInfoList:infoList]; 50 | XCTAssertEqual(self.listService.windows.count, 0, @"Finder QuickLook window was incorrectly filtered"); 51 | } 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /SwitchTests/SWGithubTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWGithubTests.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListServiceTestSuperclass.h" 16 | 17 | 18 | @interface SWGithubTests : SWWindowListServiceTestSuperclass 19 | 20 | @end 21 | 22 | 23 | @implementation SWGithubTests 24 | 25 | // This never had an Issue on Github, but it was a problem. Fixed in the Github app at the end of 2013 (thanks! <3), test kept for compatibility. 26 | - (void)testUnnamedGithubWindow; 27 | { 28 | NSDictionary *windowDescription = @{ 29 | NNWindowAlpha : @1, 30 | NNWindowBounds : DICT_FROM_RECT(((CGRect){ 31 | .size.height = 742, 32 | .size.width = 1311, 33 | .origin.x = 28, 34 | .origin.y = 22 35 | })), 36 | NNWindowIsOnscreen : @1, 37 | NNWindowLayer : @0, 38 | NNWindowMemoryUsage : @4804660, 39 | NNWindowNumber : @93247, 40 | NNWindowOwnerName : @"GitHub", 41 | NNWindowOwnerPID : @23598, 42 | NNWindowSharingState : @1, 43 | NNWindowStoreType : @2, 44 | }; 45 | NSArray *infoList = @[windowDescription]; 46 | 47 | [self updateListServiceWithInfoList:infoList]; 48 | 49 | XCTAssertEqual(self.listService.windows.count, 1, @""); 50 | XCTAssertEqual(((SWWindowGroup *)[self.listService.windows objectAtIndex:0]).windows.count, infoList.count, @""); 51 | XCTAssertEqualObjects(((SWWindowGroup *)[self.listService.windows objectAtIndex:0]).mainWindow.windowDescription, windowDescription, @""); 52 | } 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /SwitchTests/SWIsolatorTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWIsolatorTests.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 04/30/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListServiceTestSuperclass.h" 16 | 17 | 18 | @interface SWIsolatorTests : SWWindowListServiceTestSuperclass 19 | 20 | @end 21 | 22 | 23 | @implementation SWIsolatorTests 24 | 25 | - (void)testIsolatorShieldFiltering; 26 | { 27 | NSDictionary *windowDescription = @{ 28 | NNWindowLayer : @0, 29 | NNWindowName : @"", 30 | NNWindowMemoryUsage : @5186812, 31 | NNWindowIsOnscreen : @1, 32 | NNWindowSharingState : @1, 33 | NNWindowOwnerPID : @428, 34 | NNWindowNumber : @121, 35 | NNWindowOwnerName : @"Isolator", 36 | NNWindowStoreType : @2, 37 | NNWindowBounds : @{ 38 | @"Height" : @900, 39 | @"Width" : @1440, 40 | @"X" : @0, 41 | @"Y" : @0, 42 | }, 43 | NNWindowAlpha : @0.731156, 44 | }; 45 | NSArray *infoList = @[windowDescription]; 46 | 47 | [self updateListServiceWithInfoList:infoList]; 48 | 49 | XCTAssertEqual(self.listService.windows.count, 0, @""); 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /SwitchTests/SWTestApplication.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWTestApplication.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 09/29/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWApplication.h" 16 | 17 | 18 | @interface SWTestApplication : SWApplication 19 | 20 | @property (nonatomic, assign, readwrite, getter=isActiveApplication) BOOL active; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /SwitchTests/SWTestApplication.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWTestApplication.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 09/29/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWTestApplication.h" 16 | 17 | 18 | @interface SWTestApplication () 19 | 20 | @property (nonatomic, assign, readwrite) pid_t pid; 21 | @property (nonatomic, copy, readwrite) NSImage *icon; 22 | @property (nonatomic, strong, readwrite) NSString *name; 23 | @property (nonatomic, assign, readwrite, getter=isLiveApplication) BOOL liveApplication; 24 | @property (nonatomic, assign, readwrite) BOOL canBeActivated; 25 | 26 | @end 27 | 28 | 29 | @implementation SWTestApplication 30 | 31 | @synthesize pid = _pid; 32 | @synthesize icon = _icon; 33 | @synthesize name = _name; 34 | @synthesize liveApplication = _liveApplication; 35 | @synthesize canBeActivated = _canBeActivated; 36 | 37 | - (instancetype)initWithPID:(pid_t)pid name:(NSString *)name; 38 | { 39 | if (!(self = [super init])) { return nil; } 40 | 41 | self->_pid = pid; 42 | self->_name = name; 43 | self->_active = [name isEqualToString:@"Switch"]; 44 | self->_liveApplication = YES; 45 | self->_canBeActivated = ^{ 46 | NSArray *applicationNamesThatCannotBeActivated = @[ 47 | @"com.apple.security.pboxd", 48 | @"com.apple.appkit.xpc.openAndSav", 49 | ]; 50 | return ![applicationNamesThatCannotBeActivated containsObject:self.name]; 51 | }(); 52 | 53 | return self; 54 | } 55 | 56 | - (NSRunningApplication *)runningApplication; 57 | { 58 | __builtin_trap(); 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /SwitchTests/SWWindowFilteringTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // NNWindowFilteringTests.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 10/11/13. 6 | // Copyright © 2013 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #ifndef Switch_NNWindowFilteringTests_h 16 | #define Switch_NNWindowFilteringTests_h 17 | 18 | 19 | #define DICT_FROM_RECT(rect) ((__bridge_transfer NSDictionary *)CGRectCreateDictionaryRepresentation(rect)) 20 | 21 | 22 | static NSString *NNWindowAlpha; 23 | static NSString *NNWindowBounds; 24 | static NSString *NNWindowIsOnscreen; 25 | static NSString *NNWindowLayer; 26 | static NSString *NNWindowMemoryUsage; 27 | static NSString *NNWindowName; 28 | static NSString *NNWindowNumber; 29 | static NSString *NNWindowOwnerName; 30 | static NSString *NNWindowOwnerPID; 31 | static NSString *NNWindowSharingState; 32 | static NSString *NNWindowStoreType; 33 | 34 | __attribute__((constructor)) static void NNWindowKeyInit() { 35 | NNWindowAlpha = (__bridge NSString *)kCGWindowAlpha; 36 | NNWindowBounds = (__bridge NSString *)kCGWindowBounds; 37 | NNWindowIsOnscreen = (__bridge NSString *)kCGWindowIsOnscreen; 38 | NNWindowLayer = (__bridge NSString *)kCGWindowLayer; 39 | NNWindowMemoryUsage = (__bridge NSString *)kCGWindowMemoryUsage; 40 | NNWindowName = (__bridge NSString *)kCGWindowName; 41 | NNWindowNumber = (__bridge NSString *)kCGWindowNumber; 42 | NNWindowOwnerName = (__bridge NSString *)kCGWindowOwnerName; 43 | NNWindowOwnerPID = (__bridge NSString *)kCGWindowOwnerPID; 44 | NNWindowSharingState = (__bridge NSString *)kCGWindowSharingState; 45 | NNWindowStoreType = (__bridge NSString *)kCGWindowStoreType; 46 | } 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /SwitchTests/SWWindowListServiceTestSuperclass.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowListServiceTestSuperclass.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/05/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import 16 | 17 | #import "SWWindowListService.h" 18 | #import "SWWindowFilteringTests.h" 19 | #import "SWWindowGroup.h" 20 | #import "SWWindow.h" 21 | 22 | 23 | @interface SWWindowListServiceTestSuperclass : XCTestCase 24 | 25 | @property (nonatomic, strong, readonly) SWWindowListService *listService; 26 | 27 | - (void)updateListServiceWithInfoList:(NSArray *)infoList; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /SwitchTests/SWWindowListServiceTestSuperclass.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWWindowListServiceTestSuperclass.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 01/05/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | 15 | #import "SWWindowListServiceTestSuperclass.h" 16 | 17 | 18 | @interface SWWindowListService (Internal) 19 | 20 | - (void)private_updateWindowList:(NSArray *)windowInfoList; 21 | 22 | @end 23 | 24 | 25 | @implementation SWWindowListServiceTestSuperclass 26 | 27 | - (void)setUp 28 | { 29 | [super setUp]; 30 | 31 | self->_listService = [SWWindowListService new]; 32 | } 33 | 34 | - (void)tearDown 35 | { 36 | self->_listService = nil; 37 | 38 | [super tearDown]; 39 | } 40 | 41 | - (void)updateListServiceWithInfoList:(NSArray *)infoList; 42 | { 43 | [self.listService private_updateWindowList:infoList]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /SwitchTests/SwitchTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | net.numist.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SwitchTests/en.lproj/1376.ar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/SwitchTests/en.lproj/1376.ar -------------------------------------------------------------------------------- /SwitchTests/en.lproj/5891.ar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/SwitchTests/en.lproj/5891.ar -------------------------------------------------------------------------------- /SwitchTests/en.lproj/5904.ar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/numist/Switch/7d5cda1411c939a5229c80e6b194ae79d6fc41ef/SwitchTests/en.lproj/5904.ar -------------------------------------------------------------------------------- /SwitchTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /exportOptionsApp.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | method 6 | mac-application 7 | 8 | -------------------------------------------------------------------------------- /relaunch/SWTerminationListener.h: -------------------------------------------------------------------------------- 1 | // 2 | // SWTerminationListener.h 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/11/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | // Inspiration from relaunch.m: https://github.com/andymatuschak/Sparkle/blob/7316a00e9c92f54c552076a44c38241c0f1bf975/relaunch.m 15 | // 16 | 17 | @interface SWTerminationListener : NSObject 18 | 19 | - (id)initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid; 20 | - (void)relaunch; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /relaunch/SWTerminationListener.m: -------------------------------------------------------------------------------- 1 | // 2 | // SWTerminationListener.m 3 | // Switch 4 | // 5 | // Created by Scott Perry on 03/11/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | // Inspiration from relaunch.m: https://github.com/andymatuschak/Sparkle/blob/7316a00e9c92f54c552076a44c38241c0f1bf975/relaunch.m 15 | // 16 | 17 | #import "SWTerminationListener.h" 18 | 19 | 20 | @interface SWTerminationListener () 21 | 22 | @property (nonatomic, assign, readonly) const char *executablePath; 23 | @property (nonatomic, assign, readonly) pid_t parentProcessId; 24 | 25 | @end 26 | 27 | 28 | @implementation SWTerminationListener 29 | 30 | - (id)initWithExecutablePath:(const char *)execPath parentProcessId:(pid_t)ppid; 31 | { 32 | if (!(self = [super init])) { return nil; } 33 | 34 | _executablePath = execPath; 35 | _parentProcessId = ppid; 36 | if (getppid() == 1) { 37 | // ppid is launchd (1) => parent terminated already 38 | [self relaunch]; 39 | } 40 | [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(watchdog:) userInfo:nil repeats:YES]; 41 | 42 | return self; 43 | } 44 | 45 | - (void)watchdog:(NSTimer *)timer; 46 | { 47 | if (![NSRunningApplication runningApplicationWithProcessIdentifier:self.parentProcessId]) { 48 | [self relaunch]; 49 | } 50 | } 51 | 52 | - (void)relaunch; 53 | { 54 | [[NSWorkspace sharedWorkspace] openFile:[[NSFileManager defaultManager] stringWithFileSystemRepresentation:self.executablePath length:strlen(self.executablePath)]]; 55 | [[NSApplication sharedApplication] terminate:self]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /relaunch/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // relaunch 4 | // 5 | // Created by Scott Perry on 03/11/14. 6 | // Copyright © 2014 Scott Perry. 7 | // 8 | // 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: 9 | // 10 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 11 | // 12 | // 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. 13 | // 14 | // Inspiration from relaunch.m: https://github.com/andymatuschak/Sparkle/blob/7316a00e9c92f54c552076a44c38241c0f1bf975/relaunch.m 15 | // 16 | 17 | #import "SWTerminationListener.h" 18 | 19 | 20 | int main (int argc, const char * argv[]) 21 | { 22 | if (argc != 3) { return EXIT_FAILURE; } 23 | 24 | @autoreleasepool { 25 | [NSApplication sharedApplication]; 26 | 27 | static SWTerminationListener *listener; 28 | listener = [[SWTerminationListener alloc] initWithExecutablePath:argv[1] parentProcessId:atoi(argv[2])]; 29 | 30 | [[NSApplication sharedApplication] run]; 31 | } 32 | 33 | return EXIT_SUCCESS; 34 | } 35 | -------------------------------------------------------------------------------- /relaunch/relaunch-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | --------------------------------------------------------------------------------