├── .gitignore ├── DMG ├── AppIcon.icns ├── background.png ├── background@2x.png └── manifest.json ├── LICENSE ├── Menubar Toggle ├── Menubar Toggle.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── Menubar Toggle │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── 1024@128pt.png │ │ ├── 1024@128pt@2x.png │ │ ├── 1024@16pt.png │ │ ├── 1024@16pt@2x.png │ │ ├── 1024@256pt.png │ │ ├── 1024@256pt@2x.png │ │ ├── 1024@32pt.png │ │ ├── 1024@32pt@2x.png │ │ ├── 1024@512pt.png │ │ ├── 1024@512pt@2x.png │ │ └── Contents.json │ ├── Contents.json │ ├── menubarLogoDarkThemeEnabled.imageset │ │ ├── Contents.json │ │ └── menubarLogoDarkThemeEnabled.pdf │ └── menubarLogoLightThemeEnabled.imageset │ │ ├── Contents.json │ │ └── menubarLogoLightThemeEnabled.pdf │ ├── Base.lproj │ └── MainMenu.xib │ ├── Info.plist │ ├── LPWallpaperObserver.h │ ├── LPWallpaperObserver.m │ ├── Menubar Toggle.entitlements │ ├── NSImage+Luminance.h │ ├── NSImage+Luminance.m │ ├── change_theme.txt │ ├── get_theme.txt │ └── main.m ├── README.md ├── dark.png ├── icon.png ├── light.png └── toggle.sketch /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | #Pods/ 27 | -------------------------------------------------------------------------------- /DMG/AppIcon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/DMG/AppIcon.icns -------------------------------------------------------------------------------- /DMG/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/DMG/background.png -------------------------------------------------------------------------------- /DMG/background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/DMG/background@2x.png -------------------------------------------------------------------------------- /DMG/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Menubar Toggle", 3 | "icon": "AppIcon.icns", 4 | "background": "background.png", 5 | "icon-size": 80, 6 | "contents": [ 7 | { "x": 304, "y": 140, "type": "link", "path": "/Applications" }, 8 | { "x": 100, "y": 140, "type": "file", "path": "Menubar Toggle.app" } 9 | ] 10 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Savelev Igor 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E39CF8221BB805CE0036A8E8 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = E39CF8211BB805CE0036A8E8 /* AppDelegate.m */; }; 11 | E39CF8251BB805CE0036A8E8 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E39CF8241BB805CE0036A8E8 /* main.m */; }; 12 | E39CF8271BB805CE0036A8E8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E39CF8261BB805CE0036A8E8 /* Assets.xcassets */; }; 13 | E39CF82A1BB805CE0036A8E8 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = E39CF8281BB805CE0036A8E8 /* MainMenu.xib */; }; 14 | E39CF8361BB826B60036A8E8 /* NSImage+Luminance.m in Sources */ = {isa = PBXBuildFile; fileRef = E39CF8351BB826B60036A8E8 /* NSImage+Luminance.m */; }; 15 | E39CF8391BB82B3E0036A8E8 /* LPWallpaperObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = E39CF8381BB82B3E0036A8E8 /* LPWallpaperObserver.m */; }; 16 | E3CBFB521E11224B004D51A6 /* change_theme.txt in Resources */ = {isa = PBXBuildFile; fileRef = E3CBFB511E11224B004D51A6 /* change_theme.txt */; }; 17 | E3CBFB541E11227D004D51A6 /* get_theme.txt in Resources */ = {isa = PBXBuildFile; fileRef = E3CBFB531E11227D004D51A6 /* get_theme.txt */; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXFileReference section */ 21 | E39CF81D1BB805CE0036A8E8 /* Menubar Toggle.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Menubar Toggle.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 22 | E39CF8201BB805CE0036A8E8 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 23 | E39CF8211BB805CE0036A8E8 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 24 | E39CF8241BB805CE0036A8E8 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 25 | E39CF8261BB805CE0036A8E8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 26 | E39CF8291BB805CE0036A8E8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 27 | E39CF82B1BB805CE0036A8E8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 28 | E39CF8341BB826B60036A8E8 /* NSImage+Luminance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+Luminance.h"; sourceTree = ""; }; 29 | E39CF8351BB826B60036A8E8 /* NSImage+Luminance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSImage+Luminance.m"; sourceTree = ""; }; 30 | E39CF8371BB82B3E0036A8E8 /* LPWallpaperObserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LPWallpaperObserver.h; sourceTree = ""; }; 31 | E39CF8381BB82B3E0036A8E8 /* LPWallpaperObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LPWallpaperObserver.m; sourceTree = ""; }; 32 | E39CF83C1BB834E10036A8E8 /* Menubar Toggle.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "Menubar Toggle.entitlements"; sourceTree = ""; }; 33 | E3CBFB511E11224B004D51A6 /* change_theme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = change_theme.txt; sourceTree = ""; }; 34 | E3CBFB531E11227D004D51A6 /* get_theme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = get_theme.txt; sourceTree = ""; }; 35 | /* End PBXFileReference section */ 36 | 37 | /* Begin PBXFrameworksBuildPhase section */ 38 | E39CF81A1BB805CE0036A8E8 /* Frameworks */ = { 39 | isa = PBXFrameworksBuildPhase; 40 | buildActionMask = 2147483647; 41 | files = ( 42 | ); 43 | runOnlyForDeploymentPostprocessing = 0; 44 | }; 45 | /* End PBXFrameworksBuildPhase section */ 46 | 47 | /* Begin PBXGroup section */ 48 | E39CF8141BB805CE0036A8E8 = { 49 | isa = PBXGroup; 50 | children = ( 51 | E39CF81F1BB805CE0036A8E8 /* Menubar Toggle */, 52 | E39CF81E1BB805CE0036A8E8 /* Products */, 53 | ); 54 | sourceTree = ""; 55 | }; 56 | E39CF81E1BB805CE0036A8E8 /* Products */ = { 57 | isa = PBXGroup; 58 | children = ( 59 | E39CF81D1BB805CE0036A8E8 /* Menubar Toggle.app */, 60 | ); 61 | name = Products; 62 | sourceTree = ""; 63 | }; 64 | E39CF81F1BB805CE0036A8E8 /* Menubar Toggle */ = { 65 | isa = PBXGroup; 66 | children = ( 67 | E39CF83C1BB834E10036A8E8 /* Menubar Toggle.entitlements */, 68 | E39CF8341BB826B60036A8E8 /* NSImage+Luminance.h */, 69 | E39CF8351BB826B60036A8E8 /* NSImage+Luminance.m */, 70 | E39CF8371BB82B3E0036A8E8 /* LPWallpaperObserver.h */, 71 | E39CF8381BB82B3E0036A8E8 /* LPWallpaperObserver.m */, 72 | E39CF8201BB805CE0036A8E8 /* AppDelegate.h */, 73 | E39CF8211BB805CE0036A8E8 /* AppDelegate.m */, 74 | E39CF8261BB805CE0036A8E8 /* Assets.xcassets */, 75 | E39CF8281BB805CE0036A8E8 /* MainMenu.xib */, 76 | E39CF82B1BB805CE0036A8E8 /* Info.plist */, 77 | E39CF8231BB805CE0036A8E8 /* Supporting Files */, 78 | E3CBFB511E11224B004D51A6 /* change_theme.txt */, 79 | E3CBFB531E11227D004D51A6 /* get_theme.txt */, 80 | ); 81 | path = "Menubar Toggle"; 82 | sourceTree = ""; 83 | }; 84 | E39CF8231BB805CE0036A8E8 /* Supporting Files */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | E39CF8241BB805CE0036A8E8 /* main.m */, 88 | ); 89 | name = "Supporting Files"; 90 | sourceTree = ""; 91 | }; 92 | /* End PBXGroup section */ 93 | 94 | /* Begin PBXNativeTarget section */ 95 | E39CF81C1BB805CE0036A8E8 /* Menubar Toggle */ = { 96 | isa = PBXNativeTarget; 97 | buildConfigurationList = E39CF82E1BB805CE0036A8E8 /* Build configuration list for PBXNativeTarget "Menubar Toggle" */; 98 | buildPhases = ( 99 | E39CF8191BB805CE0036A8E8 /* Sources */, 100 | E39CF81A1BB805CE0036A8E8 /* Frameworks */, 101 | E39CF81B1BB805CE0036A8E8 /* Resources */, 102 | ); 103 | buildRules = ( 104 | ); 105 | dependencies = ( 106 | ); 107 | name = "Menubar Toggle"; 108 | productName = "Menubar Toggle"; 109 | productReference = E39CF81D1BB805CE0036A8E8 /* Menubar Toggle.app */; 110 | productType = "com.apple.product-type.application"; 111 | }; 112 | /* End PBXNativeTarget section */ 113 | 114 | /* Begin PBXProject section */ 115 | E39CF8151BB805CE0036A8E8 /* Project object */ = { 116 | isa = PBXProject; 117 | attributes = { 118 | LastUpgradeCheck = 0700; 119 | ORGANIZATIONNAME = Leonspok; 120 | TargetAttributes = { 121 | E39CF81C1BB805CE0036A8E8 = { 122 | CreatedOnToolsVersion = 7.0; 123 | DevelopmentTeam = 6KXZX3AW22; 124 | ProvisioningStyle = Automatic; 125 | SystemCapabilities = { 126 | com.apple.Sandbox = { 127 | enabled = 0; 128 | }; 129 | }; 130 | }; 131 | }; 132 | }; 133 | buildConfigurationList = E39CF8181BB805CE0036A8E8 /* Build configuration list for PBXProject "Menubar Toggle" */; 134 | compatibilityVersion = "Xcode 3.2"; 135 | developmentRegion = English; 136 | hasScannedForEncodings = 0; 137 | knownRegions = ( 138 | en, 139 | Base, 140 | ); 141 | mainGroup = E39CF8141BB805CE0036A8E8; 142 | productRefGroup = E39CF81E1BB805CE0036A8E8 /* Products */; 143 | projectDirPath = ""; 144 | projectRoot = ""; 145 | targets = ( 146 | E39CF81C1BB805CE0036A8E8 /* Menubar Toggle */, 147 | ); 148 | }; 149 | /* End PBXProject section */ 150 | 151 | /* Begin PBXResourcesBuildPhase section */ 152 | E39CF81B1BB805CE0036A8E8 /* Resources */ = { 153 | isa = PBXResourcesBuildPhase; 154 | buildActionMask = 2147483647; 155 | files = ( 156 | E3CBFB521E11224B004D51A6 /* change_theme.txt in Resources */, 157 | E3CBFB541E11227D004D51A6 /* get_theme.txt in Resources */, 158 | E39CF8271BB805CE0036A8E8 /* Assets.xcassets in Resources */, 159 | E39CF82A1BB805CE0036A8E8 /* MainMenu.xib in Resources */, 160 | ); 161 | runOnlyForDeploymentPostprocessing = 0; 162 | }; 163 | /* End PBXResourcesBuildPhase section */ 164 | 165 | /* Begin PBXSourcesBuildPhase section */ 166 | E39CF8191BB805CE0036A8E8 /* Sources */ = { 167 | isa = PBXSourcesBuildPhase; 168 | buildActionMask = 2147483647; 169 | files = ( 170 | E39CF8251BB805CE0036A8E8 /* main.m in Sources */, 171 | E39CF8391BB82B3E0036A8E8 /* LPWallpaperObserver.m in Sources */, 172 | E39CF8361BB826B60036A8E8 /* NSImage+Luminance.m in Sources */, 173 | E39CF8221BB805CE0036A8E8 /* AppDelegate.m in Sources */, 174 | ); 175 | runOnlyForDeploymentPostprocessing = 0; 176 | }; 177 | /* End PBXSourcesBuildPhase section */ 178 | 179 | /* Begin PBXVariantGroup section */ 180 | E39CF8281BB805CE0036A8E8 /* MainMenu.xib */ = { 181 | isa = PBXVariantGroup; 182 | children = ( 183 | E39CF8291BB805CE0036A8E8 /* Base */, 184 | ); 185 | name = MainMenu.xib; 186 | sourceTree = ""; 187 | }; 188 | /* End PBXVariantGroup section */ 189 | 190 | /* Begin XCBuildConfiguration section */ 191 | E39CF82C1BB805CE0036A8E8 /* Debug */ = { 192 | isa = XCBuildConfiguration; 193 | buildSettings = { 194 | ALWAYS_SEARCH_USER_PATHS = NO; 195 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 196 | CLANG_CXX_LIBRARY = "libc++"; 197 | CLANG_ENABLE_MODULES = YES; 198 | CLANG_ENABLE_OBJC_ARC = YES; 199 | CLANG_WARN_BOOL_CONVERSION = YES; 200 | CLANG_WARN_CONSTANT_CONVERSION = YES; 201 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 202 | CLANG_WARN_EMPTY_BODY = YES; 203 | CLANG_WARN_ENUM_CONVERSION = YES; 204 | CLANG_WARN_INT_CONVERSION = YES; 205 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 206 | CLANG_WARN_UNREACHABLE_CODE = YES; 207 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 208 | CODE_SIGN_IDENTITY = "-"; 209 | COPY_PHASE_STRIP = NO; 210 | DEBUG_INFORMATION_FORMAT = dwarf; 211 | ENABLE_STRICT_OBJC_MSGSEND = YES; 212 | ENABLE_TESTABILITY = YES; 213 | GCC_C_LANGUAGE_STANDARD = gnu99; 214 | GCC_DYNAMIC_NO_PIC = NO; 215 | GCC_NO_COMMON_BLOCKS = YES; 216 | GCC_OPTIMIZATION_LEVEL = 0; 217 | GCC_PREPROCESSOR_DEFINITIONS = ( 218 | "DEBUG=1", 219 | "$(inherited)", 220 | ); 221 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 222 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 223 | GCC_WARN_UNDECLARED_SELECTOR = YES; 224 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 225 | GCC_WARN_UNUSED_FUNCTION = YES; 226 | GCC_WARN_UNUSED_VARIABLE = YES; 227 | MACOSX_DEPLOYMENT_TARGET = 10.10; 228 | MTL_ENABLE_DEBUG_INFO = YES; 229 | ONLY_ACTIVE_ARCH = YES; 230 | SDKROOT = macosx; 231 | }; 232 | name = Debug; 233 | }; 234 | E39CF82D1BB805CE0036A8E8 /* Release */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 239 | CLANG_CXX_LIBRARY = "libc++"; 240 | CLANG_ENABLE_MODULES = YES; 241 | CLANG_ENABLE_OBJC_ARC = YES; 242 | CLANG_WARN_BOOL_CONVERSION = YES; 243 | CLANG_WARN_CONSTANT_CONVERSION = YES; 244 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INT_CONVERSION = YES; 248 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 249 | CLANG_WARN_UNREACHABLE_CODE = YES; 250 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 251 | CODE_SIGN_IDENTITY = "-"; 252 | COPY_PHASE_STRIP = NO; 253 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 254 | ENABLE_NS_ASSERTIONS = NO; 255 | ENABLE_STRICT_OBJC_MSGSEND = YES; 256 | GCC_C_LANGUAGE_STANDARD = gnu99; 257 | GCC_NO_COMMON_BLOCKS = YES; 258 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 259 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 260 | GCC_WARN_UNDECLARED_SELECTOR = YES; 261 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 262 | GCC_WARN_UNUSED_FUNCTION = YES; 263 | GCC_WARN_UNUSED_VARIABLE = YES; 264 | MACOSX_DEPLOYMENT_TARGET = 10.10; 265 | MTL_ENABLE_DEBUG_INFO = NO; 266 | SDKROOT = macosx; 267 | }; 268 | name = Release; 269 | }; 270 | E39CF82F1BB805CE0036A8E8 /* Debug */ = { 271 | isa = XCBuildConfiguration; 272 | buildSettings = { 273 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 274 | CODE_SIGN_IDENTITY = "Mac Developer"; 275 | COMBINE_HIDPI_IMAGES = YES; 276 | DEVELOPMENT_TEAM = 6KXZX3AW22; 277 | INFOPLIST_FILE = "Menubar Toggle/Info.plist"; 278 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 279 | MACOSX_DEPLOYMENT_TARGET = 10.10; 280 | PRODUCT_BUNDLE_IDENTIFIER = "com.leonspok.osx.Menubar-Toggle"; 281 | PRODUCT_NAME = "$(TARGET_NAME)"; 282 | }; 283 | name = Debug; 284 | }; 285 | E39CF8301BB805CE0036A8E8 /* Release */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 289 | CODE_SIGN_IDENTITY = "Mac Developer"; 290 | COMBINE_HIDPI_IMAGES = YES; 291 | DEVELOPMENT_TEAM = 6KXZX3AW22; 292 | INFOPLIST_FILE = "Menubar Toggle/Info.plist"; 293 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 294 | MACOSX_DEPLOYMENT_TARGET = 10.10; 295 | PRODUCT_BUNDLE_IDENTIFIER = "com.leonspok.osx.Menubar-Toggle"; 296 | PRODUCT_NAME = "$(TARGET_NAME)"; 297 | }; 298 | name = Release; 299 | }; 300 | /* End XCBuildConfiguration section */ 301 | 302 | /* Begin XCConfigurationList section */ 303 | E39CF8181BB805CE0036A8E8 /* Build configuration list for PBXProject "Menubar Toggle" */ = { 304 | isa = XCConfigurationList; 305 | buildConfigurations = ( 306 | E39CF82C1BB805CE0036A8E8 /* Debug */, 307 | E39CF82D1BB805CE0036A8E8 /* Release */, 308 | ); 309 | defaultConfigurationIsVisible = 0; 310 | defaultConfigurationName = Release; 311 | }; 312 | E39CF82E1BB805CE0036A8E8 /* Build configuration list for PBXNativeTarget "Menubar Toggle" */ = { 313 | isa = XCConfigurationList; 314 | buildConfigurations = ( 315 | E39CF82F1BB805CE0036A8E8 /* Debug */, 316 | E39CF8301BB805CE0036A8E8 /* Release */, 317 | ); 318 | defaultConfigurationIsVisible = 0; 319 | defaultConfigurationName = Release; 320 | }; 321 | /* End XCConfigurationList section */ 322 | }; 323 | rootObject = E39CF8151BB805CE0036A8E8 /* Project object */; 324 | } 325 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Menubar Toggle 4 | // 5 | // Created by Игорь Савельев on 27/09/15. 6 | // Copyright © 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Menubar Toggle 4 | // 5 | // Created by Игорь Савельев on 27/09/15. 6 | // Copyright © 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "LPWallpaperObserver.h" 11 | 12 | @interface AppDelegate () 13 | @property (strong, nonatomic) NSStatusItem *statusItem; 14 | @property (weak) IBOutlet NSMenu *menu; 15 | @property (weak) IBOutlet NSMenuItem *enabledItem; 16 | @property (weak) IBOutlet NSMenuItem *infoItem; 17 | @property (weak) IBOutlet NSMenuItem *startAtLoginItem; 18 | @end 19 | 20 | @implementation AppDelegate 21 | 22 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 23 | [self enableStatusItem]; 24 | 25 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setMenuBarDarkThemeLogo) name:kThemeChangedToDarkNotification object:nil]; 26 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(setMenuBarLightThemeLogo) name:kThemeChangedToLightNotification object:nil]; 27 | } 28 | 29 | - (void)enableStatusItem { 30 | [self hideIcon:self]; 31 | 32 | _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength]; 33 | _statusItem.title = @""; 34 | _statusItem.toolTip = @"Menubar Toggle"; 35 | _statusItem.menu = self.menu; 36 | _statusItem.menu.autoenablesItems = NO; 37 | 38 | if ([[LPWallpaperObserver sharedObserver] isDarkModeEnabled]) { 39 | [self setMenuBarDarkThemeLogo]; 40 | } else { 41 | [self setMenuBarLightThemeLogo]; 42 | } 43 | 44 | [self.infoItem setTitle:[NSString stringWithFormat:@"ver %@ (Build %@)", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"], [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]]; 45 | 46 | [self.enabledItem setState:[LPWallpaperObserver sharedObserver].autoSwithOSXTheme? NSOnState : NSOffState]; 47 | [self.startAtLoginItem setState:[self willStartAtLogin]? NSOnState : NSOffState]; 48 | } 49 | 50 | - (void)applicationWillBecomeActive:(NSNotification *)notification { 51 | [self enableStatusItem]; 52 | } 53 | 54 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 55 | // Insert code here to tear down your application 56 | } 57 | 58 | - (void)setMenuBarDarkThemeLogo { 59 | NSImage *menuBarLogo = [NSImage imageNamed:@"menubarLogoDarkThemeEnabled"]; 60 | [menuBarLogo setTemplate:YES]; 61 | _statusItem.image = menuBarLogo; 62 | } 63 | 64 | - (void)setMenuBarLightThemeLogo { 65 | NSImage *menuBarLogo = [NSImage imageNamed:@"menubarLogoLightThemeEnabled"]; 66 | [menuBarLogo setTemplate:YES]; 67 | _statusItem.image = menuBarLogo; 68 | } 69 | 70 | - (IBAction)toggleEnabled:(id)sender { 71 | [[LPWallpaperObserver sharedObserver] setAutoSwithOSXTheme:![LPWallpaperObserver sharedObserver].autoSwithOSXTheme]; 72 | [self.enabledItem setState:[LPWallpaperObserver sharedObserver].autoSwithOSXTheme? NSOnState : NSOffState]; 73 | } 74 | 75 | - (BOOL)willStartAtLogin { 76 | BOOL foundIt = NO; 77 | LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 78 | if (loginItems) { 79 | UInt32 seed = 0U; 80 | NSArray *currentLoginItems = (__bridge NSArray *)(LSSharedFileListCopySnapshot(loginItems, &seed)); 81 | for (id itemObject in currentLoginItems) { 82 | LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; 83 | 84 | UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; 85 | NSURL *URL = (__bridge NSURL *)(LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL)); 86 | foundIt = [URL isEqual:[[NSBundle mainBundle] bundleURL]]; 87 | if (foundIt) { 88 | break; 89 | } 90 | } 91 | CFRelease(loginItems); 92 | } 93 | return foundIt; 94 | } 95 | 96 | - (IBAction)toggleStartAtLogin:(id)sender { 97 | LSSharedFileListItemRef existingItem = NULL; 98 | LSSharedFileListRef loginItems = LSSharedFileListCreate(NULL, kLSSharedFileListSessionLoginItems, NULL); 99 | if (loginItems) { 100 | UInt32 seed = 0U; 101 | NSArray *currentLoginItems = (__bridge NSArray *)(LSSharedFileListCopySnapshot(loginItems, &seed)); 102 | for (id itemObject in currentLoginItems) { 103 | LSSharedFileListItemRef item = (__bridge LSSharedFileListItemRef)itemObject; 104 | 105 | UInt32 resolutionFlags = kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes; 106 | NSURL *URL = (__bridge NSURL *)(LSSharedFileListItemCopyResolvedURL(item, resolutionFlags, NULL)); 107 | BOOL foundIt = [URL isEqual:[[NSBundle mainBundle] bundleURL]]; 108 | if (foundIt) { 109 | existingItem = item; 110 | break; 111 | } 112 | } 113 | 114 | if (existingItem != NULL) { 115 | LSSharedFileListItemRemove(loginItems, existingItem); 116 | } else { 117 | LSSharedFileListInsertItemURL(loginItems, kLSSharedFileListItemBeforeFirst, 118 | NULL, NULL, (__bridge CFURLRef)[[NSBundle mainBundle] bundleURL], NULL, NULL); 119 | } 120 | 121 | CFRelease(loginItems); 122 | } 123 | 124 | [self.startAtLoginItem setState:[self willStartAtLogin]? NSOnState : NSOffState]; 125 | } 126 | 127 | - (IBAction)hideIcon:(id)sender { 128 | if (!_statusItem) { 129 | return; 130 | } 131 | [[NSStatusBar systemStatusBar] removeStatusItem:_statusItem]; 132 | _statusItem = nil; 133 | } 134 | 135 | @end 136 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@128pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@128pt.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@128pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@128pt@2x.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@16pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@16pt.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@16pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@16pt@2x.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@256pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@256pt.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@256pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@256pt@2x.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@32pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@32pt.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@32pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@32pt@2x.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@512pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@512pt.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@512pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/1024@512pt@2x.png -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "16x16", 5 | "idiom" : "mac", 6 | "filename" : "1024@16pt.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "16x16", 11 | "idiom" : "mac", 12 | "filename" : "1024@16pt@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "32x32", 17 | "idiom" : "mac", 18 | "filename" : "1024@32pt.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "32x32", 23 | "idiom" : "mac", 24 | "filename" : "1024@32pt@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "128x128", 29 | "idiom" : "mac", 30 | "filename" : "1024@128pt.png", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "size" : "128x128", 35 | "idiom" : "mac", 36 | "filename" : "1024@128pt@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "256x256", 41 | "idiom" : "mac", 42 | "filename" : "1024@256pt.png", 43 | "scale" : "1x" 44 | }, 45 | { 46 | "size" : "256x256", 47 | "idiom" : "mac", 48 | "filename" : "1024@256pt@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "512x512", 53 | "idiom" : "mac", 54 | "filename" : "1024@512pt.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "512x512", 59 | "idiom" : "mac", 60 | "filename" : "1024@512pt@2x.png", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoDarkThemeEnabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "menubarLogoDarkThemeEnabled.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoDarkThemeEnabled.imageset/menubarLogoDarkThemeEnabled.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoDarkThemeEnabled.imageset/menubarLogoDarkThemeEnabled.pdf -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoLightThemeEnabled.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "menubarLogoLightThemeEnabled.pdf" 6 | } 7 | ], 8 | "info" : { 9 | "version" : 1, 10 | "author" : "xcode" 11 | } 12 | } -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoLightThemeEnabled.imageset/menubarLogoLightThemeEnabled.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/Menubar Toggle/Menubar Toggle/Assets.xcassets/menubarLogoLightThemeEnabled.imageset/menubarLogoLightThemeEnabled.pdf -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1100 23 | LSApplicationCategoryType 24 | public.app-category.utilities 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | LSUIElement 28 | 29 | NSHumanReadableCopyright 30 | Copyright © 2015 Leonspok. All rights reserved. 31 | NSMainNibFile 32 | MainMenu 33 | NSPrincipalClass 34 | NSApplication 35 | 36 | 37 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/LPWallpaperObserver.h: -------------------------------------------------------------------------------- 1 | // 2 | // LPWallpaperObserver.h 3 | // Menubar Toggle 4 | // 5 | // Created by Игорь Савельев on 27/09/15. 6 | // Copyright © 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | extern NSString *const kThemeChangedToDarkNotification; 12 | extern NSString *const kThemeChangedToLightNotification; 13 | 14 | @interface LPWallpaperObserver : NSObject 15 | 16 | @property (nonatomic, assign) BOOL autoSwithOSXTheme; 17 | @property (nonatomic, assign, readonly, getter=isDarkModeEnabled) BOOL darkModeEnabled; 18 | 19 | + (instancetype)sharedObserver; 20 | 21 | - (void)setSuitableThemeIfNeeded; 22 | - (void)resetTheme; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/LPWallpaperObserver.m: -------------------------------------------------------------------------------- 1 | // 2 | // LPWallpaperObserver.m 3 | // Menubar Toggle 4 | // 5 | // Created by Игорь Савельев on 27/09/15. 6 | // Copyright © 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import "LPWallpaperObserver.h" 10 | #import "NSImage+Luminance.h" 11 | 12 | @import AppKit; 13 | 14 | NSString *const kThemeChangedToDarkNotification = @"ThemeChangedToDarkNotification"; 15 | NSString *const kThemeChangedToLightNotification = @"ThemeChangedToLightNotification"; 16 | 17 | static NSString *const kAutoSwithOSXThemeKey = @"autoSwithOSXTheme"; 18 | static NSString *const kImagesLuminanceInfoPlistFileName = @"imagesLuminance.plist"; 19 | 20 | @implementation LPWallpaperObserver { 21 | NSString *applicationSupportFolder; 22 | NSTimer *observingTimer; 23 | } 24 | 25 | + (instancetype)sharedObserver { 26 | static LPWallpaperObserver *__sharedObserver = nil; 27 | static dispatch_once_t onceToken; 28 | dispatch_once(&onceToken, ^{ 29 | __sharedObserver = [[LPWallpaperObserver alloc] init]; 30 | }); 31 | return __sharedObserver; 32 | } 33 | 34 | - (id)init { 35 | self = [super init]; 36 | if (self) { 37 | [self updatePaths]; 38 | 39 | if (self.autoSwithOSXTheme) { 40 | [self setAutoSwithOSXTheme:self.autoSwithOSXTheme]; 41 | } 42 | } 43 | return self; 44 | } 45 | 46 | - (void)updatePaths { 47 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES); 48 | applicationSupportFolder = [[paths firstObject] stringByAppendingPathComponent:@"Menubar Toggle"]; 49 | 50 | if (![[NSFileManager defaultManager] fileExistsAtPath:applicationSupportFolder]) { 51 | [[NSFileManager defaultManager] createDirectoryAtPath:applicationSupportFolder withIntermediateDirectories:YES attributes:nil error:nil]; 52 | } 53 | } 54 | 55 | #pragma mark Getters and Setters 56 | 57 | - (BOOL)autoSwithOSXTheme { 58 | if (NSAppKitVersionNumber < NSAppKitVersionNumber10_10) { 59 | return NO; 60 | } 61 | 62 | return [[NSUserDefaults standardUserDefaults] boolForKey:kAutoSwithOSXThemeKey]; 63 | } 64 | 65 | - (void)setAutoSwithOSXTheme:(BOOL)autoSwithOSXTheme { 66 | if (NSAppKitVersionNumber < NSAppKitVersionNumber10_10) { 67 | autoSwithOSXTheme = NO; 68 | } 69 | 70 | [[NSUserDefaults standardUserDefaults] setBool:autoSwithOSXTheme forKey:kAutoSwithOSXThemeKey]; 71 | [[NSUserDefaults standardUserDefaults] synchronize]; 72 | 73 | if (!autoSwithOSXTheme) { 74 | [self resetTheme]; 75 | [observingTimer invalidate]; 76 | observingTimer = nil; 77 | } else { 78 | [self setSuitableThemeIfNeeded]; 79 | dispatch_async(dispatch_get_main_queue(), ^{ 80 | observingTimer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(setSuitableThemeIfNeeded) userInfo:nil repeats:YES]; 81 | }); 82 | } 83 | } 84 | 85 | - (BOOL)isDarkModeEnabled { 86 | NSAppleScript *script = [[NSAppleScript alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"get_theme" withExtension:@"txt"] error:nil]; 87 | NSAppleEventDescriptor *dsc = [script executeAndReturnError:nil]; 88 | return dsc.booleanValue; 89 | } 90 | 91 | - (void)resetTheme { 92 | [self setDarkTheme:NO]; 93 | } 94 | 95 | #pragma mark Wallpapers Observing 96 | 97 | - (BOOL)themeShouldBeDark { 98 | CGFloat averageLuminance = 0.0f; 99 | for (NSScreen *screen in [NSScreen screens]) { 100 | NSString *path = [[[NSWorkspace sharedWorkspace] desktopImageURLForScreen:screen] path]; 101 | averageLuminance += [self luminanceForImageWithPath:path]; 102 | } 103 | if ([NSScreen screens].count > 0) { 104 | averageLuminance = averageLuminance/[NSScreen screens].count; 105 | } 106 | return averageLuminance < 0.375; 107 | } 108 | 109 | - (void)setDarkTheme:(BOOL)dark { 110 | NSString *scriptSource = [[NSString alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"change_theme" withExtension:@"txt"] encoding:NSUTF8StringEncoding error:nil]; 111 | scriptSource = [scriptSource stringByReplacingOccurrencesOfString:@"" withString:(dark? @"true" : @"false")]; 112 | NSAppleScript *script = [[NSAppleScript alloc] initWithSource:scriptSource]; 113 | [script executeAndReturnError:nil]; 114 | dispatch_async(dispatch_get_main_queue(), ^{ 115 | if (dark) { 116 | [[NSNotificationCenter defaultCenter] postNotificationName:kThemeChangedToDarkNotification object:nil]; 117 | } else { 118 | [[NSNotificationCenter defaultCenter] postNotificationName:kThemeChangedToLightNotification object:nil]; 119 | } 120 | }); 121 | } 122 | 123 | - (void)setSuitableThemeIfNeeded { 124 | if (NSAppKitVersionNumber < NSAppKitVersionNumber10_10) { 125 | return; 126 | } 127 | 128 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ 129 | BOOL shouldBeDark = [self themeShouldBeDark]; 130 | BOOL darkModeEnabled = [self isDarkModeEnabled]; 131 | if (shouldBeDark != darkModeEnabled) { 132 | dispatch_async(dispatch_get_main_queue(), ^{ 133 | [self setDarkTheme:shouldBeDark]; 134 | }); 135 | } 136 | }); 137 | } 138 | 139 | #pragma mark Images Managing 140 | 141 | - (CGFloat)luminanceForImageWithPath:(NSString *)path { 142 | NSString *plistFilePath = [applicationSupportFolder stringByAppendingPathComponent:kImagesLuminanceInfoPlistFileName]; 143 | NSMutableDictionary *info = [[NSMutableDictionary alloc] initWithContentsOfFile:plistFilePath]; 144 | 145 | if ([info objectForKey:path]) { 146 | return [[info objectForKey:path] doubleValue]; 147 | } 148 | 149 | if (!info) { 150 | info = [NSMutableDictionary dictionary]; 151 | } 152 | 153 | NSImage *image = [[NSImage alloc] initWithContentsOfFile:path]; 154 | if (image) { 155 | CGFloat luminance = image.luminance; 156 | [info setObject:@(luminance) forKey:path]; 157 | [info writeToFile:plistFilePath atomically:YES]; 158 | return luminance; 159 | } else { 160 | return 0.5f; 161 | } 162 | } 163 | 164 | @end 165 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/Menubar Toggle.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/NSImage+Luminance.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+Luminance.h 3 | // Unsplash Wallpaper 4 | // 5 | // Created by Игорь Савельев on 06/06/15. 6 | // Copyright (c) 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSImage (Luminance) 12 | 13 | @property (nonatomic, readonly) CGFloat luminance; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/NSImage+Luminance.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSImage+Luminance.m 3 | // Unsplash Wallpaper 4 | // 5 | // Created by Игорь Савельев on 06/06/15. 6 | // Copyright (c) 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import "NSImage+Luminance.h" 10 | #import 11 | 12 | static NSString *const kCalculatedLuminanceKey = @"CALCULATED LUMINANCE"; 13 | 14 | @implementation NSImage (Luminance) 15 | 16 | - (NSBitmapImageRep *)bitmapImageRepresentation { 17 | int width = [self size].width; 18 | int height = [self size].height; 19 | 20 | if(width < 1 || height < 1) { 21 | return nil; 22 | } 23 | 24 | NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] 25 | initWithBitmapDataPlanes:NULL 26 | pixelsWide:width 27 | pixelsHigh:height 28 | bitsPerSample:8 29 | samplesPerPixel:4 30 | hasAlpha:YES 31 | isPlanar:NO 32 | colorSpaceName:NSDeviceRGBColorSpace 33 | bytesPerRow:(width * 4) 34 | bitsPerPixel:32]; 35 | 36 | NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:rep]; 37 | [NSGraphicsContext saveGraphicsState]; 38 | [NSGraphicsContext setCurrentContext:ctx]; 39 | [self drawAtPoint:NSZeroPoint 40 | fromRect:NSZeroRect 41 | operation:NSCompositeCopy fraction:1.0]; 42 | [ctx flushGraphics]; 43 | [NSGraphicsContext restoreGraphicsState]; 44 | 45 | return rep; 46 | } 47 | 48 | - (CGFloat)luminance { 49 | NSNumber *lum = objc_getAssociatedObject(self, &kCalculatedLuminanceKey); 50 | if (lum) { 51 | return [lum doubleValue]; 52 | } 53 | 54 | NSBitmapImageRep *rep = [self bitmapImageRepresentation]; 55 | 56 | int width = [self size].width; 57 | int height = [self size].height; 58 | 59 | CGFloat totalLuminance = 0; 60 | CGFloat r; 61 | CGFloat g; 62 | CGFloat b; 63 | NSColor *color; 64 | NSInteger n = 0; 65 | for (NSInteger i = 0; i < height; i+=10) { 66 | for (NSInteger j = 0; j < width; j+=10) { 67 | color = [rep colorAtX:j y:i]; 68 | [color getRed:&r green:&g blue:&b alpha:NULL]; 69 | CGFloat luminance = (0.299*r + 0.587*g + 0.114*b); 70 | totalLuminance += luminance; 71 | n++; 72 | } 73 | } 74 | CGFloat averageLuminance = totalLuminance/n; 75 | 76 | objc_setAssociatedObject(self, &kCalculatedLuminanceKey, @(averageLuminance), OBJC_ASSOCIATION_RETAIN); 77 | return averageLuminance; 78 | } 79 | 80 | @end 81 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/change_theme.txt: -------------------------------------------------------------------------------- 1 | tell application "System Events" 2 | tell appearance preferences to set dark mode to 3 | end tell 4 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/get_theme.txt: -------------------------------------------------------------------------------- 1 | tell application "System Events" 2 | tell appearance preferences to get dark mode 3 | end tell 4 | -------------------------------------------------------------------------------- /Menubar Toggle/Menubar Toggle/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Menubar Toggle 4 | // 5 | // Created by Игорь Савельев on 27/09/15. 6 | // Copyright © 2015 Leonspok. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Menubar Toggle 2 | 3 | 4 | 5 | Dark wallpaper - dark OS X, light wallpaper - light OS X. That's so simple. 6 | 7 | Download Menubar Toggle [here](https://github.com/leonspok/Menubar-Toggle/releases). 8 | 9 | *** 10 | 11 | Folder **/DMG** contains all necessary files to create **.dmg** file with [appdmg](https://github.com/LinusU/node-appdmg). 12 | -------------------------------------------------------------------------------- /dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/dark.png -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/icon.png -------------------------------------------------------------------------------- /light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/light.png -------------------------------------------------------------------------------- /toggle.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/leonspok/Menubar-Toggle/26360c146628b414caca1ce8aab14f55e18a6484/toggle.sketch --------------------------------------------------------------------------------