Is there an API, that can lock the screen as the menu bar entry you can add from Keychain
preferences?
This Keychain
function is (was) lock
If you actually want to do what keychain does (ie just lock the screen, don't go to login window), it's quite easy:
io_registry_entry_t r = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
if (r) {
IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), sleep ? kCFBooleanTrue);
IOObjectRelease(r);
}
However, this only works if the user has 'Require Password after sleep or screen saver begins' set to 'immediately'. But, you can just set it to immediately for them and then set it back to what it was when you are done. Turns out getting that to take effect can be pretty tricky (see this answer for more info) but it can be done. Put it all together and you have something like:
- (void)lockScreen;
{
int screenSaverDelayUserSetting = 0;
screenSaverDelayUserSetting = [self readScreensaveDelay];
if (screenSaverDelayUserSetting != 0) {
// if the delay isn't already 0, temporarily set it to 0 so the screen locks immediately.
[self setScreensaverDelay:0];
[self touchSecurityPreferences];
}
io_registry_entry_t r = IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/IOResources/IODisplayWrangler");
if (r) {
IORegistryEntrySetCFProperty(r, CFSTR("IORequestIdle"), sleep ? kCFBooleanTrue : kCFBooleanFalse);
IOObjectRelease(r);
}
if (screenSaverDelayUserSetting != 0) {
[self setScreensaverDelay:screenSaverDelayUserSetting];
[self launchAndQuitSecurityPreferences];
}
}
- (void)touchSecurityPreferences;
{
// necessary for screen saver setting changes to take effect on file-vault-enabled systems
// NOTE: this *only* works when going from non-zero settings of askForPasswordDelay to zero.
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource: @"tell application \"System Events\" to tell security preferences to set require password to wake to true"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}
- (void)launchAndQuitSecurityPreferences;
{
// necessary for screen saver setting changes to take effect on file-vault-enabled systems when going from a askForPasswordDelay setting of zero to a non-zero setting
NSAppleScript *kickSecurityPreferencesScript = [[[NSAppleScript alloc] initWithSource:
@"tell application \"System Preferences\"\n"
@" tell anchor \"General\" of pane \"com.apple.preference.security\" to reveal\n"
@" activate\n"
@"end tell\n"
@"delay 0\n"
@"tell application \"System Preferences\" to quit"] autorelease];
[kickSecurityPreferencesScript executeAndReturnError:nil];
}
- (int)readScreensaveDelay;
{
NSArray *arguments = @[@"read",@"com.apple.screensaver",@"askForPasswordDelay"];
NSTask *readDelayTask = [[[NSTask alloc] init] autorelease];
[readDelayTask setArguments:arguments];
[readDelayTask setLaunchPath: @"/usr/bin/defaults"];
NSPipe *pipe = [NSPipe pipe];
[readDelayTask setStandardOutput:pipe];
NSFileHandle *file = [pipe fileHandleForReading];
[readDelayTask launch];
NSData *resultData = [file readDataToEndOfFile];
NSString *resultString = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
return resultString.intValue;
}
- (void)setScreensaverDelay:(int)delay;
{
NSArray *arguments = @[@"write",@"com.apple.screensaver",@"askForPasswordDelay", [NSString stringWithFormat:@"%i", delay]];
NSTask *resetDelayTask = [[[NSTask alloc] init] autorelease];
[resetDelayTask setArguments:arguments];
[resetDelayTask setLaunchPath: @"/usr/bin/defaults"];
[resetDelayTask launch];
}