Skip to content

Commit

Permalink
macOS changes
Browse files Browse the repository at this point in the history
  • Loading branch information
jcoffland committed Jan 12, 2024
1 parent ed4d2d0 commit e88d016
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 87 deletions.
113 changes: 40 additions & 73 deletions src/fah/client/osx/OSXOSImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include <cbang/event/Base.h>
#include <cbang/event/Event.h>
#include <cbang/os/PowerManagement.h>
#include <cbang/os/MacOSUtilities.h>

#include <IOKit/IOMessage.h>
#include <IOKit/ps/IOPSKeys.h>
Expand All @@ -55,52 +54,54 @@ using namespace std;


static const CFTimeInterval kCFTimeIntervalMax =
std::numeric_limits<CFTimeInterval>::max();
numeric_limits<CFTimeInterval>::max();

enum {
kDisplayPowerUnknown = -1,
kDisplayPowerOff = 0,
kDisplayPowerDimmed = 3,
kDisplayPowerOn = 4
kDisplayPowerOff = 0,
kDisplayPowerDimmed = 3,
kDisplayPowerOn = 4
};


namespace {
#pragma mark c callbacks

void consoleUserCB(SCDynamicStoreRef s, CFArrayRef keys, void *info) {
OSXOSImpl::instance().consoleUserChanged(s, keys, info);
}

void displayPowerCB(void *ctx, io_service_t service,
natural_t mtype, void *marg) {

void displayPowerCB(
void *ctx, io_service_t service, natural_t mtype, void *marg) {
OSXOSImpl::instance().displayPowerChanged(ctx, service, mtype, marg);
}


void updateTimerCB(CFRunLoopTimerRef timer, void *info) {
OSXOSImpl::instance().updateTimerFired(timer, info);
}


void heartbeatTimerCB(CFRunLoopTimerRef timer, void *info) {
LOG_DEBUG(5, "heartbeat on thread " << pthread_self() <<
(pthread_main_np() ? " main" : ""));
}


void noteQuitCB(CFNotificationCenterRef center, void *observer,
CFNotificationName name, const void *object,
CFDictionaryRef info) {
std::string n = CFStringGetCStringPtr(name, kCFStringEncodingUTF8);
LOG_INFO(3, "Received notification " << n);
LOG_INFO(3, "Received notification "
<< CFStringGetCStringPtr(name, kCFStringEncodingUTF8));
OSXOSImpl::instance().requestExit();
}

}


OSXOSImpl *OSXOSImpl::singleton = 0;


OSXOSImpl::OSXOSImpl(App &app) : OS(app), consoleUser(CFSTR("unknown")) {
OSXOSImpl::OSXOSImpl(App &app) : OS(app), consoleUser("unknown") {
if (singleton) THROW("There can be only one OSXOSImpl");
singleton = this;
initialize();
Expand All @@ -109,10 +110,7 @@ OSXOSImpl::OSXOSImpl(App &app) : OS(app), consoleUser(CFSTR("unknown")) {

OSXOSImpl::~OSXOSImpl() {
// Stop any update timer
if (updateTimer) {
CFRunLoopTimerInvalidate(updateTimer);
CFRelease(updateTimer);
}
if (updateTimer) CFRunLoopTimerInvalidate(updateTimer);

// Deregister for display power changes
if (displayWrangler) IOObjectRelease(displayWrangler);
Expand All @@ -122,21 +120,11 @@ OSXOSImpl::~OSXOSImpl() {
kCFRunLoopDefaultMode);

if (displayNotePort) IONotificationPortDestroy(displayNotePort);

if (displayNotifier) IOObjectRelease(displayNotifier);

// Deregister for console user changes
if (consoleUserRLS) {
CFRunLoopSourceInvalidate(consoleUserRLS);
CFRelease(consoleUserRLS);
}

if (consoleUserDS) {
SCDynamicStoreSetNotificationKeys(consoleUserDS, 0, 0);
CFRelease(consoleUserDS);
}

if (consoleUser) CFRelease(consoleUser);
if (consoleUserRLS) CFRunLoopSourceInvalidate(consoleUserRLS);
if (consoleUserDS) SCDynamicStoreSetNotificationKeys(consoleUserDS, 0, 0);

CFNotificationCenterRef nc = CFNotificationCenterGetDarwinNotifyCenter();
CFNotificationCenterRemoveEveryObserver(nc, this);
Expand Down Expand Up @@ -174,18 +162,12 @@ void OSXOSImpl::addHeartbeatTimerToRunLoop(CFRunLoopRef loop) {
// note this may fail silently
if (!loop) return;

CFRunLoopTimerRef timer =
MacOSRef<CFRunLoopTimerRef> timer =
CFRunLoopTimerCreate(0, 0, 3600, 0, 0, heartbeatTimerCB, 0);
if (timer) {
CFRunLoopAddTimer(loop, timer, kCFRunLoopDefaultMode);
CFRelease(timer);
}
if (timer) CFRunLoopAddTimer(loop, timer, kCFRunLoopDefaultMode);
}


const char *OSXOSImpl::getName() const {return "macosx";}


void OSXOSImpl::dispatch() {
if (!pthread_main_np())
THROW("OSXOSImpl::dispatch() must be called on main thread");
Expand Down Expand Up @@ -224,8 +206,10 @@ void OSXOSImpl::finishInit() {
void OSXOSImpl::updateSystemIdle() {
bool shouldBeIdle = displayPower == kDisplayPowerOff || loginwindowIsActive ||
screensaverIsActive || screenIsLocked;

if (shouldBeIdle == systemIsIdle) return;
systemIsIdle = shouldBeIdle;

event->activate();
}

Expand Down Expand Up @@ -266,6 +250,7 @@ void OSXOSImpl::delayedUpdateSystemIdle(int delay) {
} else if (delay < currentDelay) {
// Use sooner of current fire date and candidateTime
CFAbsoluteTime currentTime = CFRunLoopTimerGetNextFireDate(updateTimer);

if (candidateTime < currentTime) {
CFRunLoopTimerSetNextFireDate(updateTimer, candidateTime);
currentDelay = delay;
Expand All @@ -274,7 +259,7 @@ void OSXOSImpl::delayedUpdateSystemIdle(int delay) {
}


void OSXOSImpl::displayDidDim() {displayPower = kDisplayPowerDimmed;}
void OSXOSImpl::displayDidDim() {displayPower = kDisplayPowerDimmed;}
void OSXOSImpl::displayDidUndim() {displayPower = kDisplayPowerOn;}


Expand Down Expand Up @@ -321,17 +306,16 @@ void OSXOSImpl::displayPowerChanged(void *context, io_service_t service,

int OSXOSImpl::getCurrentDisplayPower() {
// will only return values kDisplayPowerUnknown thru kDisplayPowerOn
int state = kDisplayPowerUnknown;
int state = kDisplayPowerUnknown;
int maxstate = 4;

if (!displayWrangler)
displayWrangler = IOServiceGetMatchingService
(kIOMasterPortDefault, IOServiceNameMatching("IODisplayWrangler"));

if (displayWrangler) {
CFMutableDictionaryRef props = 0;

auto kr = IORegistryEntryCreateCFProperties(displayWrangler, &props, 0, 0);
MacOSRef<CFMutableDictionaryRef> props;
auto kr = IORegistryEntryCreateCFProperties(displayWrangler, props, 0, 0);

if (kr == KERN_SUCCESS) {
auto dict = (CFMutableDictionaryRef)CFDictionaryGetValue
Expand All @@ -357,7 +341,6 @@ int OSXOSImpl::getCurrentDisplayPower() {
}
}

if (props) CFRelease(props);
IOObjectRelease(displayWrangler);
displayWrangler = 0;
}
Expand Down Expand Up @@ -424,17 +407,14 @@ bool OSXOSImpl::registerForDisplayPowerNotifications() {
}


void OSXOSImpl::consoleUserChanged(SCDynamicStoreRef store,
CFArrayRef changedKeys, void *info) {
if (consoleUser) CFRelease(consoleUser);
consoleUser = SCDynamicStoreCopyConsoleUser(consoleUserDS, 0, 0);
void OSXOSImpl::consoleUserChanged(
SCDynamicStoreRef store, CFArrayRef changedKeys, void *info) {
consoleUser = MacOSString(SCDynamicStoreCopyConsoleUser(consoleUserDS, 0, 0));

LOG_DEBUG(4, __func__ << "() " << MacOSUtilities::toString(consoleUser));
LOG_DEBUG(4, __func__ << "() " << (string)consoleUser);

bool wasActive = loginwindowIsActive;
loginwindowIsActive = !consoleUser || !CFStringGetLength(consoleUser) ||
CFEqual(consoleUser, CFSTR("loginwindow"));

loginwindowIsActive = consoleUser.empty() || consoleUser == "loginwindow";
bool changed = wasActive != loginwindowIsActive;

if (changed || !store) {
Expand All @@ -450,9 +430,9 @@ bool OSXOSImpl::registerForConsoleUserNotifications() {
consoleUserDS = SCDynamicStoreCreate
(0, CFSTR("FAHClient Console User Watcher"), consoleUserCB, &context);

CFStringRef consoleUserKey = SCDynamicStoreKeyCreateConsoleUser(0);
CFStringRef values[] = {consoleUserKey};
CFArrayRef keys =
MacOSString consoleUserKey = SCDynamicStoreKeyCreateConsoleUser(0);
CFStringRef values[] = {(CFStringRef)consoleUserKey};
MacOSRef<CFArrayRef> keys =
CFArrayCreate(0, (const void **)values, 1, &kCFTypeArrayCallBacks);

bool ok = consoleUserKey && keys && consoleUserDS;
Expand All @@ -467,17 +447,12 @@ bool OSXOSImpl::registerForConsoleUserNotifications() {
if (!ok) {
if (consoleUserDS) {
SCDynamicStoreSetNotificationKeys(consoleUserDS, 0, 0);
CFRelease(consoleUserDS);
consoleUserDS = 0;
}

if (consoleUser) CFRelease(consoleUser);
consoleUser = CFSTR("unknown");
consoleUser = "unknown";
}

if (consoleUserKey) CFRelease(consoleUserKey);
if (keys) CFRelease(keys);

// Initial consoleUser value will be set in finishInit
return ok;
}
Expand All @@ -488,24 +463,16 @@ bool OSXOSImpl::registerForDarwinNotifications() {

if (!nc) return false;

std::string user = "nobody";
string user = "nobody";
struct passwd *pwent = getpwuid(getuid());
if (pwent && pwent->pw_name) user = pwent->pw_name;

std::string key = "org.foldingathome.fahclient." + user + ".stop";
CFStringRef name =
CFStringCreateWithCString(0, key.c_str(), kCFStringEncodingUTF8);

if (name) {
CFNotificationCenterAddObserver(
nc, (void *)this, &noteQuitCB, name, 0,
CFNotificationSuspensionBehaviorCoalesce);
CFRelease(name);
MacOSString name(string("org.foldingathome.fahclient." + user + ".stop"));
CFNotificationCenterAddObserver(
nc, (void *)this, &noteQuitCB, name, 0,
CFNotificationSuspensionBehaviorCoalesce);

return true;
}

return false;
return true;
}


Expand Down
29 changes: 15 additions & 14 deletions src/fah/client/osx/OSXOSImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <fah/client/OS.h>

#include <cbang/os/Thread.h>
#include <cbang/os/MacOSUtilities.h>

#include <CoreFoundation/CoreFoundation.h>
#include <SystemConfiguration/SystemConfiguration.h>
Expand All @@ -46,25 +47,25 @@ namespace FAH {
static OSXOSImpl *singleton;

std::atomic<bool> systemIsIdle = false;
bool screensaverIsActive = false;
bool screenIsLocked = false;
bool loginwindowIsActive = false;
bool screensaverIsActive = false;
bool screenIsLocked = false;
bool loginwindowIsActive = false;

io_service_t displayWrangler = 0;
IONotificationPortRef displayNotePort = 0;
CFRunLoopSourceRef displayNoteSource = 0;
io_object_t displayNotifier = 0;
io_object_t displayNotifier = 0;
cb::MacOSRef<IONotificationPortRef> displayNotePort;
cb::MacOSRef<CFRunLoopSourceRef> displayNoteSource;

SCDynamicStoreRef consoleUserDS = 0;
CFRunLoopSourceRef consoleUserRLS = 0;
CFStringRef consoleUser = 0;
cb::MacOSRef<SCDynamicStoreRef> consoleUserDS;
cb::MacOSRef<CFRunLoopSourceRef> consoleUserRLS;
std::string consoleUser;

CFRunLoopTimerRef updateTimer = 0;
cb::MacOSRef<CFRunLoopTimerRef> updateTimer;

int idleDelay = 5;
int currentDelay = 0;
int idleDelay = 5;
int currentDelay = 0;
int idleOnLoginwindowDelay = 30;
int displayPower = 0;
int displayPower = 0;

public:
OSXOSImpl(App &app);
Expand All @@ -73,7 +74,7 @@ namespace FAH {
static OSXOSImpl &instance();

// From OS
const char *getName() const;
const char *getName() const {return "macosx";}
bool isSystemIdle() const {return systemIsIdle;}
void dispatch();

Expand Down

0 comments on commit e88d016

Please sign in to comment.