4646#include < pwd.h>
4747#include < unistd.h>
4848
49+ #include < fah/screen-agent/defines.h>
50+
4951using namespace FAH ::Client;
5052using namespace cb ;
5153using namespace std ;
6062
6163
6264namespace {
65+ CFStringRef kScreenIdle = CFSTR(SCREEN_IDLE_NOTIFICATION);
66+ CFStringRef kScreenNotIdle = CFSTR(SCREEN_NOT_IDLE_NOTIFICATION);
67+
6368#pragma mark c callbacks
6469 void consoleUserCB (SCDynamicStoreRef s, CFArrayRef keys, void *info) {
6570 OSXOSImpl::instance ().consoleUserChanged (s, keys, info);
@@ -85,6 +90,20 @@ namespace {
8590 << CFStringGetCStringPtr (name, kCFStringEncodingUTF8 ));
8691 OSXOSImpl::instance ().requestExit ();
8792 }
93+
94+
95+ void screenIdleCB (CFNotificationCenterRef center, void *observer,
96+ CFNotificationName name, const void *object,
97+ CFDictionaryRef info) {
98+ OSXOSImpl::instance ().noteScreenIdle ();
99+ }
100+
101+
102+ void screenNotIdleCB (CFNotificationCenterRef center, void *observer,
103+ CFNotificationName name, const void *object,
104+ CFDictionaryRef info) {
105+ OSXOSImpl::instance ().noteScreenNotIdle ();
106+ }
88107}
89108
90109
@@ -187,9 +206,10 @@ void OSXOSImpl::finishInit() {
187206
188207
189208void OSXOSImpl::updateSystemIdle () {
190- bool shouldBeIdle = displayPower == kDisplayPowerOff || loginwindowIsActive ||
191- screensaverIsActive || screenIsLocked;
192-
209+ bool shouldBeIdle;
210+ if (gotScreenNotIdleRecently ()) shouldBeIdle = false ;
211+ else shouldBeIdle = displayPower == kDisplayPowerOff || loginwindowIsActive ||
212+ gotScreenIdleRecently ();
193213 if (shouldBeIdle == systemIsIdle) return ;
194214 systemIsIdle = shouldBeIdle;
195215
@@ -415,10 +435,57 @@ bool OSXOSImpl::registerForConsoleUserNotifications() {
415435}
416436
417437
438+ void OSXOSImpl::noteScreenIdle () {
439+ screenIdleExpiry =
440+ dispatch_time (DISPATCH_TIME_NOW, SCREEN_NOTIFICATION_EXPIRES * NSEC_PER_SEC);
441+ bool wasIdle = screenIdle;
442+ screenIdle = true ;
443+ dispatch_after (screenIdleExpiry + NSEC_PER_SEC, dispatch_get_main_queue (), ^{
444+ updateSystemIdle ();
445+ });
446+ if (!wasIdle) delayedUpdateSystemIdle (5 );
447+ }
448+
449+
450+ void OSXOSImpl::noteScreenNotIdle () {
451+ screenNotIdleExpiry =
452+ dispatch_time (DISPATCH_TIME_NOW, SCREEN_NOTIFICATION_EXPIRES * NSEC_PER_SEC);
453+ screenNotIdle = true ;
454+ dispatch_after (screenNotIdleExpiry + NSEC_PER_SEC,dispatch_get_main_queue (),^{
455+ updateSystemIdle ();
456+ });
457+ updateSystemIdle ();
458+ }
459+
460+
461+ bool OSXOSImpl::gotScreenIdleRecently () {
462+ if (!screenIdle) return false ;
463+ if (dispatch_time (DISPATCH_TIME_NOW, 0 ) < screenIdleExpiry) return true ;
464+ screenIdle = false ;
465+ return false ;
466+ }
467+
468+
469+ bool OSXOSImpl::gotScreenNotIdleRecently () {
470+ if (!screenNotIdle) return false ;
471+ if (dispatch_time (DISPATCH_TIME_NOW, 0 ) < screenNotIdleExpiry) return true ;
472+ screenNotIdle = false ;
473+ return false ;
474+ }
475+
476+
418477bool OSXOSImpl::registerForDarwinNotifications () {
419478 CFNotificationCenterRef nc = CFNotificationCenterGetDarwinNotifyCenter ();
420479 if (!nc) return false ;
421480
481+ CFNotificationCenterAddObserver (
482+ nc, (void *)this , &screenIdleCB, kScreenIdle , 0 ,
483+ CFNotificationSuspensionBehaviorCoalesce);
484+
485+ CFNotificationCenterAddObserver (
486+ nc, (void *)this , &screenNotIdleCB, kScreenNotIdle , 0 ,
487+ CFNotificationSuspensionBehaviorCoalesce);
488+
422489 string user = " nobody" ;
423490 struct passwd *pwent = getpwuid (getuid ());
424491 if (pwent && pwent->pw_name ) user = pwent->pw_name ;
0 commit comments