├── NeonWindows.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ ├── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ └── xcuserdata │ │ └── rensbreur.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── rensbreur.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── xcschememanagement.plist ├── NeonWindows └── NeonWindows.m ├── README.md └── screenshot.png /NeonWindows.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2E9CA92723576D5300DE955A /* NeonWindows.m in Sources */ = {isa = PBXBuildFile; fileRef = 2E3582FE220B3C9900F67675 /* NeonWindows.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXFileReference section */ 14 | 2E3582F9220B3C9900F67675 /* libNeonWindows.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libNeonWindows.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 15 | 2E3582FE220B3C9900F67675 /* NeonWindows.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NeonWindows.m; sourceTree = ""; }; 16 | 2EB8E5A9237F88C10056F1A9 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 17 | /* End PBXFileReference section */ 18 | 19 | /* Begin PBXFrameworksBuildPhase section */ 20 | 2E3582F7220B3C9900F67675 /* Frameworks */ = { 21 | isa = PBXFrameworksBuildPhase; 22 | buildActionMask = 2147483647; 23 | files = ( 24 | ); 25 | runOnlyForDeploymentPostprocessing = 0; 26 | }; 27 | /* End PBXFrameworksBuildPhase section */ 28 | 29 | /* Begin PBXGroup section */ 30 | 2E3582F0220B3C9900F67675 = { 31 | isa = PBXGroup; 32 | children = ( 33 | 2EB8E5A9237F88C10056F1A9 /* README.md */, 34 | 2E3582FB220B3C9900F67675 /* NeonWindows */, 35 | 2E3582FA220B3C9900F67675 /* Products */, 36 | ); 37 | sourceTree = ""; 38 | }; 39 | 2E3582FA220B3C9900F67675 /* Products */ = { 40 | isa = PBXGroup; 41 | children = ( 42 | 2E3582F9220B3C9900F67675 /* libNeonWindows.dylib */, 43 | ); 44 | name = Products; 45 | sourceTree = ""; 46 | }; 47 | 2E3582FB220B3C9900F67675 /* NeonWindows */ = { 48 | isa = PBXGroup; 49 | children = ( 50 | 2E3582FE220B3C9900F67675 /* NeonWindows.m */, 51 | ); 52 | path = NeonWindows; 53 | sourceTree = ""; 54 | }; 55 | /* End PBXGroup section */ 56 | 57 | /* Begin PBXHeadersBuildPhase section */ 58 | 2E3582F5220B3C9900F67675 /* Headers */ = { 59 | isa = PBXHeadersBuildPhase; 60 | buildActionMask = 2147483647; 61 | files = ( 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXHeadersBuildPhase section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 2E3582F8220B3C9900F67675 /* NeonWindows */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 2E358302220B3C9900F67675 /* Build configuration list for PBXNativeTarget "NeonWindows" */; 71 | buildPhases = ( 72 | 2E3582F5220B3C9900F67675 /* Headers */, 73 | 2E3582F6220B3C9900F67675 /* Sources */, 74 | 2E3582F7220B3C9900F67675 /* Frameworks */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = NeonWindows; 81 | productName = DarkSidebar; 82 | productReference = 2E3582F9220B3C9900F67675 /* libNeonWindows.dylib */; 83 | productType = "com.apple.product-type.library.dynamic"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 2E3582F1220B3C9900F67675 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 1010; 92 | ORGANIZATIONNAME = "Rens Breur"; 93 | TargetAttributes = { 94 | 2E3582F8220B3C9900F67675 = { 95 | CreatedOnToolsVersion = 10.1; 96 | LastSwiftMigration = 1010; 97 | }; 98 | }; 99 | }; 100 | buildConfigurationList = 2E3582F4220B3C9900F67675 /* Build configuration list for PBXProject "NeonWindows" */; 101 | compatibilityVersion = "Xcode 9.3"; 102 | developmentRegion = en; 103 | hasScannedForEncodings = 0; 104 | knownRegions = ( 105 | en, 106 | ); 107 | mainGroup = 2E3582F0220B3C9900F67675; 108 | productRefGroup = 2E3582FA220B3C9900F67675 /* Products */; 109 | projectDirPath = ""; 110 | projectRoot = ""; 111 | targets = ( 112 | 2E3582F8220B3C9900F67675 /* NeonWindows */, 113 | ); 114 | }; 115 | /* End PBXProject section */ 116 | 117 | /* Begin PBXSourcesBuildPhase section */ 118 | 2E3582F6220B3C9900F67675 /* Sources */ = { 119 | isa = PBXSourcesBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | 2E9CA92723576D5300DE955A /* NeonWindows.m in Sources */, 123 | ); 124 | runOnlyForDeploymentPostprocessing = 0; 125 | }; 126 | /* End PBXSourcesBuildPhase section */ 127 | 128 | /* Begin XCBuildConfiguration section */ 129 | 2E358300220B3C9900F67675 /* Debug */ = { 130 | isa = XCBuildConfiguration; 131 | buildSettings = { 132 | ALWAYS_SEARCH_USER_PATHS = NO; 133 | CLANG_ANALYZER_NONNULL = YES; 134 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 135 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 136 | CLANG_CXX_LIBRARY = "libc++"; 137 | CLANG_ENABLE_MODULES = YES; 138 | CLANG_ENABLE_OBJC_ARC = YES; 139 | CLANG_ENABLE_OBJC_WEAK = YES; 140 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 141 | CLANG_WARN_BOOL_CONVERSION = YES; 142 | CLANG_WARN_COMMA = YES; 143 | CLANG_WARN_CONSTANT_CONVERSION = YES; 144 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 145 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 146 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 147 | CLANG_WARN_EMPTY_BODY = YES; 148 | CLANG_WARN_ENUM_CONVERSION = YES; 149 | CLANG_WARN_INFINITE_RECURSION = YES; 150 | CLANG_WARN_INT_CONVERSION = YES; 151 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 152 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 153 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 154 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 155 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 156 | CLANG_WARN_STRICT_PROTOTYPES = YES; 157 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 158 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 159 | CLANG_WARN_UNREACHABLE_CODE = YES; 160 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 161 | CODE_SIGN_IDENTITY = "-"; 162 | COPY_PHASE_STRIP = NO; 163 | DEBUG_INFORMATION_FORMAT = dwarf; 164 | ENABLE_STRICT_OBJC_MSGSEND = YES; 165 | ENABLE_TESTABILITY = YES; 166 | GCC_C_LANGUAGE_STANDARD = gnu11; 167 | GCC_DYNAMIC_NO_PIC = NO; 168 | GCC_NO_COMMON_BLOCKS = YES; 169 | GCC_OPTIMIZATION_LEVEL = 0; 170 | GCC_PREPROCESSOR_DEFINITIONS = ( 171 | "DEBUG=1", 172 | "$(inherited)", 173 | ); 174 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 175 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 176 | GCC_WARN_UNDECLARED_SELECTOR = YES; 177 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 178 | GCC_WARN_UNUSED_FUNCTION = YES; 179 | GCC_WARN_UNUSED_VARIABLE = YES; 180 | MACOSX_DEPLOYMENT_TARGET = 10.14; 181 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 182 | MTL_FAST_MATH = YES; 183 | ONLY_ACTIVE_ARCH = YES; 184 | SDKROOT = macosx; 185 | }; 186 | name = Debug; 187 | }; 188 | 2E358301220B3C9900F67675 /* Release */ = { 189 | isa = XCBuildConfiguration; 190 | buildSettings = { 191 | ALWAYS_SEARCH_USER_PATHS = NO; 192 | CLANG_ANALYZER_NONNULL = YES; 193 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 194 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 195 | CLANG_CXX_LIBRARY = "libc++"; 196 | CLANG_ENABLE_MODULES = YES; 197 | CLANG_ENABLE_OBJC_ARC = YES; 198 | CLANG_ENABLE_OBJC_WEAK = YES; 199 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 200 | CLANG_WARN_BOOL_CONVERSION = YES; 201 | CLANG_WARN_COMMA = YES; 202 | CLANG_WARN_CONSTANT_CONVERSION = YES; 203 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 204 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 205 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 206 | CLANG_WARN_EMPTY_BODY = YES; 207 | CLANG_WARN_ENUM_CONVERSION = YES; 208 | CLANG_WARN_INFINITE_RECURSION = YES; 209 | CLANG_WARN_INT_CONVERSION = YES; 210 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 211 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 212 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 213 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 214 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 215 | CLANG_WARN_STRICT_PROTOTYPES = YES; 216 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 217 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 218 | CLANG_WARN_UNREACHABLE_CODE = YES; 219 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 220 | CODE_SIGN_IDENTITY = "-"; 221 | COPY_PHASE_STRIP = NO; 222 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 223 | ENABLE_NS_ASSERTIONS = NO; 224 | ENABLE_STRICT_OBJC_MSGSEND = YES; 225 | GCC_C_LANGUAGE_STANDARD = gnu11; 226 | GCC_NO_COMMON_BLOCKS = YES; 227 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 228 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 229 | GCC_WARN_UNDECLARED_SELECTOR = YES; 230 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 231 | GCC_WARN_UNUSED_FUNCTION = YES; 232 | GCC_WARN_UNUSED_VARIABLE = YES; 233 | MACOSX_DEPLOYMENT_TARGET = 10.14; 234 | MTL_ENABLE_DEBUG_INFO = NO; 235 | MTL_FAST_MATH = YES; 236 | SDKROOT = macosx; 237 | }; 238 | name = Release; 239 | }; 240 | 2E358303220B3C9900F67675 /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | CLANG_ENABLE_MODULES = YES; 244 | CODE_SIGN_STYLE = Automatic; 245 | DYLIB_COMPATIBILITY_VERSION = 1; 246 | DYLIB_CURRENT_VERSION = 1; 247 | EXECUTABLE_PREFIX = lib; 248 | LD_RUNPATH_SEARCH_PATHS = ( 249 | "$(inherited)", 250 | "@executable_path/../Frameworks", 251 | "@loader_path/../Frameworks", 252 | ); 253 | PRODUCT_NAME = "$(TARGET_NAME)"; 254 | SKIP_INSTALL = YES; 255 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 256 | SWIFT_VERSION = 4.2; 257 | }; 258 | name = Debug; 259 | }; 260 | 2E358304220B3C9900F67675 /* Release */ = { 261 | isa = XCBuildConfiguration; 262 | buildSettings = { 263 | CLANG_ENABLE_MODULES = YES; 264 | CODE_SIGN_STYLE = Automatic; 265 | DYLIB_COMPATIBILITY_VERSION = 1; 266 | DYLIB_CURRENT_VERSION = 1; 267 | EXECUTABLE_PREFIX = lib; 268 | LD_RUNPATH_SEARCH_PATHS = ( 269 | "$(inherited)", 270 | "@executable_path/../Frameworks", 271 | "@loader_path/../Frameworks", 272 | ); 273 | PRODUCT_NAME = "$(TARGET_NAME)"; 274 | SKIP_INSTALL = YES; 275 | SWIFT_VERSION = 4.2; 276 | }; 277 | name = Release; 278 | }; 279 | /* End XCBuildConfiguration section */ 280 | 281 | /* Begin XCConfigurationList section */ 282 | 2E3582F4220B3C9900F67675 /* Build configuration list for PBXProject "NeonWindows" */ = { 283 | isa = XCConfigurationList; 284 | buildConfigurations = ( 285 | 2E358300220B3C9900F67675 /* Debug */, 286 | 2E358301220B3C9900F67675 /* Release */, 287 | ); 288 | defaultConfigurationIsVisible = 0; 289 | defaultConfigurationName = Release; 290 | }; 291 | 2E358302220B3C9900F67675 /* Build configuration list for PBXNativeTarget "NeonWindows" */ = { 292 | isa = XCConfigurationList; 293 | buildConfigurations = ( 294 | 2E358303220B3C9900F67675 /* Debug */, 295 | 2E358304220B3C9900F67675 /* Release */, 296 | ); 297 | defaultConfigurationIsVisible = 0; 298 | defaultConfigurationName = Release; 299 | }; 300 | /* End XCConfigurationList section */ 301 | }; 302 | rootObject = 2E3582F1220B3C9900F67675 /* Project object */; 303 | } 304 | -------------------------------------------------------------------------------- /NeonWindows.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NeonWindows.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /NeonWindows.xcodeproj/project.xcworkspace/xcuserdata/rensbreur.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rensbreur/NeonWindows/e52cf6dbedce0eacaeb73ca531c441b537c1c162/NeonWindows.xcodeproj/project.xcworkspace/xcuserdata/rensbreur.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /NeonWindows.xcodeproj/xcuserdata/rensbreur.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /NeonWindows.xcodeproj/xcuserdata/rensbreur.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | DarkSidebar.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | NeonWindows.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /NeonWindows/NeonWindows.m: -------------------------------------------------------------------------------- 1 | // 2 | // NeonWindows.m 3 | // NeonWindows 4 | // 5 | // Created by Rens Breur on 06/11/2019. 6 | // Copyright © 2019 Rens Breur. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface NeonWindows: NSObject 13 | 14 | @end 15 | 16 | @interface NSThemeFrame: NSObject 17 | 18 | - (id)initWithFrame:(struct CGRect)arg1 styleMask:(unsigned long long)arg2 owner:(id)arg3; 19 | - (id)_cuiOptionsForCornerMaskForWindowType:(struct __CFString *)arg1; 20 | 21 | @end 22 | 23 | @implementation NeonWindows 24 | 25 | + (void)load { 26 | static dispatch_once_t onceToken; 27 | 28 | dispatch_once(&onceToken, ^{ 29 | 30 | // Border around window 31 | [self on:[NSThemeFrame class] change:@selector(initWithFrame:styleMask:owner:) to:@selector(_initWithFrame:styleMask:owner:)]; 32 | [self on:[NSThemeFrame class] change:@selector(_cuiOptionsForCornerMaskForWindowType:) to:@selector(__cuiOptionsForCornerMaskForWindowType:)]; 33 | 34 | // No window shadow 35 | [self on:[NSWindow class] change:@selector(hasShadow) to:@selector(_hasShadow)]; 36 | 37 | // Controls color 38 | [self onClass:[NSColor class] change:@selector(controlAccentColor) to:@selector(_color)]; 39 | [self onClass:[NSColor class] change:@selector(currentControlTint) to:@selector(_color)]; 40 | [self onClass:[NSColor class] change:@selector(selectedControlColor) to:@selector(_color)]; 41 | [self onClass:[NSColor class] change:@selector(highlightColor) to:@selector(_color)]; 42 | [self onClass:[NSColor class] change:@selector(selectedContentBackgroundColor) to:@selector(_color)]; 43 | [self onClass:[NSColor class] change:@selector(controlHighlightColor) to:@selector(_color)]; 44 | [self onClass:[NSColor class] change:@selector(controlColor) to:@selector(_color)]; 45 | 46 | [self onClass:[NSColor class] change:@selector(currentControlTint) to:@selector(_currentControlTint)]; 47 | 48 | }); 49 | } 50 | 51 | + (void)on:(Class)class 52 | change:(SEL)from 53 | to:(SEL)to 54 | { 55 | Method orig = class_getInstanceMethod(class, from); 56 | Method hook = class_getInstanceMethod([self class], to); 57 | 58 | class_addMethod(class, to, method_getImplementation(orig), method_getTypeEncoding(orig)); 59 | class_replaceMethod(class, from, method_getImplementation(hook), method_getTypeEncoding(hook)); 60 | } 61 | 62 | + (void)onClass:(Class)class 63 | change:(SEL)from 64 | to:(SEL)to 65 | { 66 | Method orig = class_getClassMethod(class, from); 67 | Method hook = class_getClassMethod([self class], to); 68 | 69 | class_addMethod(object_getClass((id)class), to, method_getImplementation(orig), method_getTypeEncoding(orig)); 70 | class_replaceMethod(object_getClass((id)class), from, method_getImplementation(hook), method_getTypeEncoding(hook)); 71 | } 72 | 73 | NSColor *neonWindowsReadColorFromDefaults() 74 | { 75 | NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; 76 | return [NSColor colorWithRed:[defaults floatForKey:@"cr"] green:[defaults floatForKey:@"cg"] blue:[defaults floatForKey:@"cb"] alpha:1]; 77 | } 78 | 79 | static NSColor *_neonWindowsColor; 80 | 81 | NSColor *neonWindowsColor() 82 | { 83 | if (!_neonWindowsColor) { 84 | _neonWindowsColor = neonWindowsReadColorFromDefaults(); 85 | } 86 | return _neonWindowsColor; 87 | } 88 | 89 | - (id)_initWithFrame:(struct CGRect)arg1 styleMask:(unsigned long long)arg2 owner:(id)arg3; 90 | { 91 | self = [self _initWithFrame:arg1 styleMask:arg2 owner:arg3]; 92 | 93 | NSView *frame = (NSView *)self; 94 | frame.wantsLayer = YES; 95 | frame.layer.borderColor = neonWindowsColor().CGColor; 96 | frame.layer.borderWidth = 1.5; 97 | 98 | return self; 99 | } 100 | 101 | - (id)__cuiOptionsForCornerMaskForWindowType:(struct __CFString *)arg1; 102 | { 103 | return nil; 104 | } 105 | 106 | - (BOOL)_hasShadow { 107 | return NO; 108 | } 109 | 110 | + (NSColor *)_color { 111 | return neonWindowsColor(); 112 | } 113 | 114 | + (NSControlTint)_currentControlTint { 115 | return NSBlueControlTint; 116 | } 117 | 118 | @end 119 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # NeonWindows 2 | 3 | ![Screenshot](screenshot.png) 4 | 5 | NeonWindows is a plugin to color window border colors on macOS Catalina. 6 | 7 | ``` 8 | defaults write -app MyApp "cr" {red_value} 9 | defaults write -app MyApp "cg" {green_value} 10 | defaults write -app MyApp "cb" {blue_value} 11 | ``` 12 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rensbreur/NeonWindows/e52cf6dbedce0eacaeb73ca531c441b537c1c162/screenshot.png --------------------------------------------------------------------------------