Skip to content

Instantly share code, notes, and snippets.

@thenextman
Created May 21, 2020 18:49
Show Gist options
  • Save thenextman/41ff0068c74d33d366c4df56d3b079f6 to your computer and use it in GitHub Desktop.
Save thenextman/41ff0068c74d33d366c4df56d3b079f6 to your computer and use it in GitHub Desktop.
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import <AppKit/AppKit.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <Carbon/Carbon.h>
#import <CoreFoundation/CoreFoundation.h>
static CFStringRef CopyCurrentConsoleUsername(SCDynamicStoreRef store)
{
CFStringRef result;
result = SCDynamicStoreCopyConsoleUser(store, NULL, NULL);
if ((result) && CFEqual(result, CFSTR("loginwindow")))
{
CFRelease(result);
result = NULL;
}
return result;
}
static CFStringRef gCurrentConsoleUser;
static void onSCConsoleUserChange(SCDynamicStoreRef store, CFArrayRef changedKeys, void* info)
{
CFStringRef currentConsoleUser;
Boolean didChange;
currentConsoleUser = CopyCurrentConsoleUsername(store);
didChange = (gCurrentConsoleUser != NULL) != (currentConsoleUser != NULL);
if (!didChange && (gCurrentConsoleUser != NULL) )
{
didChange = !CFEqual(gCurrentConsoleUser, currentConsoleUser);
}
if (didChange)
{
if (gCurrentConsoleUser)
CFRelease(gCurrentConsoleUser);
gCurrentConsoleUser = currentConsoleUser;
if (gCurrentConsoleUser)
CFRetain(gCurrentConsoleUser);
NSLog(@"gCurrentConsoleUser: %@", (__bridge NSString*) gCurrentConsoleUser);
}
}
OSStatus onCarbonNotification(EventHandlerCallRef nextHandler, EventRef switchEvent, void* userData)
{
if (GetEventKind(switchEvent)== kEventSystemUserSessionActivated)
{
NSLog(@"kEventSystemUserSessionActivated");
}
else if (GetEventKind(switchEvent)== kEventSystemUserSessionDeactivated)
{
NSLog(@"kEventSystemUserSessionDeactivated");
}
return noErr;
}
void onDistNotification(CFNotificationCenterRef center, void* observer, CFNotificationName name, const void* object, CFDictionaryRef userInfo)
{
NSLog(@"onDistNotification: %@", (__bridge NSString*) name);
}
@interface Notifier : NSObject
{
}
@end
@implementation Notifier
- (void)onWorkspaceNotification:(NSNotification*)notification
{
if ([notification.name isEqualToString:NSWorkspaceSessionDidBecomeActiveNotification])
{
NSLog(@"NSWorkspaceSessionDidBecomeActiveNotification");
}
else if ([notification.name isEqualToString:NSWorkspaceSessionDidBecomeActiveNotification])
{
NSLog(@"NSWorkspaceSessionDidResignActiveNotification");
}
}
- (instancetype)init
{
self = [super init];
if (self)
{
//
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(onWorkspaceNotification:)
name:NSWorkspaceSessionDidBecomeActiveNotification
object:nil];
[[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:self
selector:@selector(onWorkspaceNotification:)
name:NSWorkspaceSessionDidResignActiveNotification
object:nil];
//
EventTypeSpec switchEventTypes[2];
EventHandlerUPP switchEventHandler;
switchEventTypes[0].eventClass = kEventClassSystem;
switchEventTypes[0].eventKind = kEventSystemUserSessionDeactivated;
switchEventTypes[1].eventClass = kEventClassSystem;
switchEventTypes[1].eventKind = kEventSystemUserSessionActivated;
switchEventHandler = NewEventHandlerUPP(onCarbonNotification);
InstallApplicationEventHandler(switchEventHandler, 2, switchEventTypes, NULL, NULL);
//
Boolean success;
SCDynamicStoreRef store;
CFStringRef key;
CFArrayRef keys;
CFRunLoopSourceRef rls;
store = SCDynamicStoreCreate(NULL, CFSTR("com.apple.dts.ConsoleUser"), onSCConsoleUserChange, NULL);
key = SCDynamicStoreKeyCreateConsoleUser(NULL);
keys = CFArrayCreate(NULL, (const void **) &key, 1, &kCFTypeArrayCallBacks);
success = SCDynamicStoreSetNotificationKeys(store, keys, NULL);
rls = SCDynamicStoreCreateRunLoopSource(NULL, store, 0);
CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);
gCurrentConsoleUser = CopyCurrentConsoleUsername(store);
NSLog(@"gCurrentConsoleUser: %@", (__bridge NSString*) gCurrentConsoleUser);
//
CFNotificationCenterRef distNc = CFNotificationCenterGetDistributedCenter();
CFNotificationCenterAddObserver(distNc, (__bridge const void *) self, onDistNotification, (__bridge CFStringRef) @"com.apple.screensaver.didlaunch", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, (__bridge const void *) self, onDistNotification, (__bridge CFStringRef) @"com.apple.screensaver.didstart", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, NULL, onDistNotification, (__bridge CFStringRef) @"com.apple.screensaver.didstop", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, NULL, onDistNotification, (__bridge CFStringRef) @"com.apple.shieldWindowRaised", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, NULL, onDistNotification, (__bridge CFStringRef) @"com.apple.shieldWindowLowered", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, NULL, onDistNotification, (__bridge CFStringRef) @"com.apple.screenIsLocked", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, NULL, onDistNotification, (__bridge CFStringRef) @"com.apple.screenIsUnlocked", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, (__bridge const void *) self, onDistNotification, (__bridge CFStringRef) @"com.apple.sessionDidMoveOffConsole", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
CFNotificationCenterAddObserver(distNc, (__bridge const void *) self, onDistNotification, (__bridge CFStringRef) @"com.apple.sessionDidMoveOnConsole", nil,
CFNotificationSuspensionBehaviorDeliverImmediately);
// com.apple.userWillLogOut
}
return self;
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool
{
Notifier* notifier = [[Notifier alloc] init];
CFRunLoopRun();
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment