7

This image is from SystemPreferences > Appearance enter image description here

I want to know How do I get that value programmatically?

I ask because I am drawing a window with a customized titlebar and I want it to resemble (in behavior) as much as possible to normal (non-customized) cocoa windows.

Maybe a terminal command I can pipe or is there an cocoa API that does this?

EDIT:

Answer (thanks to NSGod)

- (void)mouseUp:(NSEvent *)event{

    if ([event clickCount] == 2) {
        //Get settings from "System Preferences" >  "Appearance" > "Double-click on windows title bar to minimize"
        NSString *const MDAppleMiniaturizeOnDoubleClickKey = @"AppleMiniaturizeOnDoubleClick";
        NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
        // [userDefaults addSuiteNamed:NSGlobalDomain]; // unnecessary
        BOOL shouldMiniaturize = [[userDefaults objectForKey:MDAppleMiniaturizeOnDoubleClickKey] boolValue];
        if (shouldMiniaturize) {
            [self miniaturize:self];
        }
    }
}

Later I found that Appearance (Aqua/Graphite) can be found:

NSString * const kAppleAquaColorVariant = @"AppleAquaColorVariant";
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// [userDefaults addSuiteNamed:NSGlobalDomain]; // unnecessary  
NSNumber *color = [userDefaults objectForKey:kAppleAquaColorVariant];
if ([color intValue] == 6) {//graphite is 6 
    imageName = [imageName stringByAppendingFormat:@"_graphite"];
}else{//defaults to aqua, (aqua is 1)
    imageName = [imageName stringByAppendingFormat:@"_colorsryg"];
}

Which can be helpful too :)

NSGod
  • 22,699
  • 3
  • 58
  • 66
nacho4d
  • 43,720
  • 45
  • 157
  • 240

1 Answers1

5

The way I would do it is probably read the value in from user defaults.

NSString * const MDAppleMiniaturizeOnDoubleClickKey = @"AppleMiniaturizeOnDoubleClick";

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
// [userDefaults addSuiteNamed:NSGlobalDomain]; // unnecessary

NSNumber *miniaturize = [userDefaults
                     objectForKey:MDAppleMiniaturizeOnDoubleClickKey];

NSLog(@"AppleMiniaturizeOnDoubleClick == %@",
                ([miniaturize boolValue] ? @"YES" : @"NO"));

(This preference setting is stored in the invisible .GlobalPreferences.plist in your ~/Library/Preferences/ folder).

Note that by default, the "double-click to minimize" option is turned off, so if you check for the presence of the AppleMiniaturizeOnDoubleClick and it returns nil, that means it is off. (User defaults only start to store values if they differ from the defaults).

This key is the same in Leopard as it is in Snow Leopard. (It hasn't changed in Lion or Mountain Lion either).

Of course, there is a secret (private) method in NSWindow, -(BOOL)_shouldMiniaturizeOnDoubleClick, but I wouldn't recommend using private methods.

[UPDATE] Regarding Catfish_Man's comment: you are correct in that the line [userDefaults addSuiteNamed:NSGlobalDomain]; is unnecessary, as NSUserDefaults already has the ability to read global preferences. (I modified the code above to reflect this).

"Additionally, NSGlobalDomain is not translated to .GlobalPreferences.plist for that method."

I'm not sure I follow you there. NSUserDefaults is built on top of CFPreferences which defines the following 6 constants:

Application:

 kCFPreferencesAnyApplication,
 kCFPreferencesCurrentApplication

Host:

 kCFPreferencesAnyHost,
 kCFPreferencesCurrentHost

User:

 kCFPreferencesAnyUser,
 kCFPreferencesCurrentUser

Given a fictional application bundle identifier of "com.markdouma.App" and a single host (based on your current network location that won't change for this example), there are generally 8 locations where preference information could be stored on your disk. (NOTE: The paths shown are for demonstration purposes only; the exact file path locations are subject to change). The 8 different locations arise from the different combination of the CFPreferences constants:

/Library/Preferences/.GlobalPreferences.plist (kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesAnyHost)

/Library/Preferences/com.markdouma.App.plist
(kCFPreferencesCurrentApplication, kCFPreferencesAnyUser, kCFPreferencesAnyHost)

/Library/Preferences/ByHost/.GlobalPreferences.UNIQUE_HOST_IDENTIFIER.plist (kCFPreferencesAnyApplication, kCFPreferencesAnyUser, kCFPreferencesCurrentHost)

/Library/Preferences/ByHost/com.markdouma.App.UNIQUE_HOST_IDENTIFIER.plist (kCFPreferencesCurrentApplication, kCFPreferencesAnyUser, kCFPreferencesCurrentHost)

~/Library/Preferences/.GlobalPreferences.plist (kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)

~/Library/Preferences/com.markdouma.App.plist (kCFPreferencesCurrentApplication, kCFPreferencesCurrentUser, kCFPreferencesAnyHost)

~/Library/Preferences/ByHost/.GlobalPreferences.UNIQUE_HOST_IDENTIFIER.plist (kCFPreferencesAnyApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)

~/Library/Preferences/ByHost/com.markdouma.App.UNIQUE_HOST_IDENTIFIER.plist (kCFPreferencesCurrentApplication, kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)

While NSUserDefaults can only write to the domain combination shown in italics, it automatically has read access to the domain combinations shown in bold. In other words, without having to do anything, I can automatically run the following code and print the results:

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

NSNumber *miniaturize = [userDefaults
                 objectForKey:@"AppleMiniaturizeOnDoubleClick"];

NSNumber *fastUserSwitching = [userDefaults
                 objectForKey:@"MultipleSessionEnabled"];

NSLog(@"AppleMiniaturizeOnDoubleClick == %@",
            ([miniaturize boolValue] ? @"YES" : @"NO"));

NSLog(@"MultipleSessionEnabled == %@",
            ([fastUserSwitching boolValue] ? @"YES" : @"NO"));

Running that code on my system prints the following results:

 AppleMiniaturizeOnDoubleClick == YES
 MultipleSessionEnabled == YES

This makes sense, since I have both Fast User Switching and Double-click to minimize options enabled. MultipleSessionsEnabled is stored in the local domain at /Library/Preferences/.GlobalPreferences.plist, and AppleMiniaturizeOnDoubleClick is stored in the user domain at ~/Library/Preferences/.GlobalPreferences.plist.

Sample project: NSUserDefaultsFinagler.zip

"Additionally additionally, that's slow. Please don't do this."

Sorry, but that makes no sense (assuming that we've agreed that we're no longer using addSuiteNamed:). User defaults are cached by the application, making calls take in the matter of milliseconds. Wouldn't there be little noticeable difference between asking user defaults for the value for a key that represents a local application value or one that represents a global value?

AFAIK, this is the only "legal" (App-store-compatible) way to achieve the OP's goal. If there's another more efficient means, then please elaborate.

NSGod
  • 22,699
  • 3
  • 58
  • 66
  • 3
    [userDefaults addSuiteNamed:NSGlobalDomain]; is worse than useless. The global domain is included in the default search list for NSUserDefaults. Additionally, NSGlobalDomain is not translated to .GlobalPreferences.plist for that method. Additionally additionally, that's slow. Please don't do this. – Catfish_Man Dec 06 '12 at 01:31
  • 1
    Regarding "Additionally, NSGlobalDomain is not translated to .GlobalPreferences.plist for that method.", NSGlobalDomain has a value of @"NSGlobalDomain", which is not the same as CFPreferences constants. NSUserDefaults internally translates NSGlobalDomain to kCFPreferencesAnyApplication, but only in contexts where it makes sense to do so. Regarding the speed concern: -addSuiteNamed triggers a lock & copy-on-write behavior in CFPreferences that is much slower than most other preferences operations. It's expected that it generally won't be called much. – Catfish_Man Dec 08 '12 at 00:26
  • (The tradeoff for copy-on-write is that it makes normal lookups significantly faster due to not having to lock the search list. Lookups outweigh suite calls by at least a factor of a million generally) – Catfish_Man Dec 08 '12 at 00:27
  • on Mavericks, doing NSGod's code will report this in your log: "Using NSGlobalDomain as an NSUserDefaults suite name does not make sense and will not work. Break on _NSUserDefaults_Log_Nonsensical_Suites to find this" ###From NSUserDefaults docs: " defaults database is created automatically for each user. The NSUserDefaults class does not currently support per-host preferences. To do this, you must use the CFPreferences API (see Preferences Utilities Reference). However, NSUserDefaults correctly reads per-host preferences, so you can safely mix CFPreferences code with NSUserDefaults code." – Vivek Gani Feb 13 '14 at 01:06
  • @VivekGani: I already agreed that the use of `[userDefaults addSuiteNamed:NSGlobalDomain]` doesn't make any sense, that's why I commented it out as unnecessary almost 4 years ago. (It's unnecessary since `NSUserDefaults` can already read from the global domain). I've updated my "answer" in the original question to reflect the updated code. – NSGod Feb 25 '14 at 21:32