Skip to content

Commit 0c47180

Browse files
committed
Support osx idle on screensaver, screenlock
Add fah-screen-agent Support idle/not idle notifications Add tools.scons
1 parent 555ffcd commit 0c47180

File tree

11 files changed

+590
-21
lines changed

11 files changed

+590
-21
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
*.app
2222

2323
# Build byproducts
24+
/bin
2425
/build
2526
/package.txt
2627
/package-description.txt

SConstruct

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,15 @@ if env['PLATFORM'] == 'win32' or int(env.get('cross_mingw', 0)):
6464
duplicate = 0)
6565
Default(hide_console)
6666

67+
tools = SConscript('src/tools.scons', variant_dir = 'build', duplicate = 0)
68+
Default(tools)
69+
Depends(tools, client)
6770
# Clean
68-
Clean(client, ['build', 'config.log'])
71+
Clean(client, ['bin', 'build', 'config.log'])
6972

7073
# Dist
7174
docs = ['README.md', 'CHANGELOG.md', 'LICENSE']
72-
distfiles = docs + [client, 'images/fahlogo.png']
75+
distfiles = docs + client + tools + ['images/fahlogo.png']
7376
if env['PLATFORM'] == 'posix':
7477
distfiles.append('install/lin/fah-client.service')
7578
if hide_console is not None: distfiles.append(hide_console)
@@ -122,14 +125,18 @@ if 'package' in COMMAND_LINE_TARGETS:
122125
# Specify components for the osx distribution pkg
123126
client_home = '.'
124127
client_root = client_home + '/build/pkg/root'
125-
pkg_files = [[str(client[0]), 'usr/local/bin/', 0o755],
126-
['build/install/osx/fahclient.url',
128+
pkg_files = [['build/install/osx/fahclient.url',
127129
'Applications/Folding@home/fahclient.url', 0o644],
128130
['build/install/osx/uninstall.url',
129131
'Applications/Folding@home/uninstall.url', 0o644],
130132
['build/install/osx/launchd.plist',
131133
'Library/LaunchDaemons/' +
132-
'org.foldingathome.fahclient.plist', 0o644]]
134+
'org.foldingathome.fahclient.plist', 0o644],
135+
['build/install/osx/fah-screen-agent.plist','Library/LaunchAgents/' +
136+
'org.foldingathome.fah-screen-agent.plist', 0o644]]
137+
for tool in client + tools:
138+
pkg_files += [[str(tool), 'usr/local/bin/', 0o755]]
139+
133140
pkg_components = [
134141
{
135142
# name is component pkg file name and name shown in installer
@@ -145,7 +152,7 @@ if 'package' in COMMAND_LINE_TARGETS:
145152
# default build/pkg/root, as per cbang config pkg module
146153
'root' : client_root,
147154
# relative to root
148-
'sign_tools' : ['usr/local/bin/fah-client'],
155+
'sign_tools' : ['usr/local/bin/*'],
149156
'must_close_apps': [
150157
'org.foldingathome.fahviewer',
151158
'org.foldingathome.fahcontrol',
@@ -220,7 +227,6 @@ if 'package' in COMMAND_LINE_TARGETS:
220227
pkg_background = 'fah-opacity-50.png',
221228
pkg_customize = 'always',
222229
pkg_target = pkg_target,
223-
pkg_arch = env.get('package_arch', 'x86_64'),
224230
pkg_components = pkg_components,
225231
)
226232

install/osx/fah-screen-agent.plist

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>KeepAlive</key>
6+
<dict>
7+
<key>SuccessfulExit</key>
8+
<false/>
9+
</dict>
10+
<key>Label</key>
11+
<string>org.foldingathome.fah-screen-agent</string>
12+
<key>LimitLoadToSessionType</key>
13+
<string>Aqua</string>
14+
<key>LowPriorityIO</key>
15+
<true/>
16+
<key>Program</key>
17+
<string>/usr/local/bin/fah-screen-agent</string>
18+
<key>RunAtLoad</key>
19+
<true/>
20+
<key>StandardOutPath</key>
21+
<string>/dev/null</string>
22+
<key>Umask</key>
23+
<integer>18</integer>
24+
</dict>
25+
</plist>

install/osx/scripts/postinstall

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,28 @@ chmod -R u+rwX,go-w "$RUN_DIR"
1111
chown -R nobody:nobody "$RUN_DIR"
1212

1313
PLIST=/Library/LaunchDaemons/org.foldingathome.fahclient.plist
14+
AGENT_PLIST="/Library/LaunchAgents/org.foldingathome.fah-screen-agent.plist"
1415

1516
"$SCRIPTS"/organize-credits.sh &
1617

1718
# Start service
18-
chmod 0644 "$PLIST"
19+
chmod 0644 "$PLIST" "$AGENT_PLIST"
1920
launchctl load -w "$PLIST"
2021

2122
# start, in case RunAtLoad is false
2223
launchctl start org.foldingathome.fahclient || true
2324

25+
# restart any running agents in other sessions
26+
# note that this does not reload their launchd jobs
27+
killall -HUP fah-screen-agent || true
28+
29+
# start agent in user's gui session
30+
conuser=$(/usr/bin/stat -f "%Su" /dev/console) || conuser="root"
31+
conuid=$(/usr/bin/id -u "$conuser") || conuid=0
32+
if [[ $conuid != 0 ]]; then
33+
launchctl bootstrap gui/$conuid "$AGENT_PLIST" || true
34+
fi
35+
2436
# Don't launch GUI if CLI install
2537
[ "$COMMAND_LINE_INSTALL" == "1" ] && exit 0
2638

install/osx/scripts/preinstall

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ SCRIPTS="$(dirname "$0")"
1010
OLD_LAUNCHD="/Library/LaunchDaemons/FAHClient.plist"
1111
OLD_LAUNCHD2="/Library/LaunchDaemons/edu.stanford.folding.fahclient.plist"
1212
NEW_LAUNCHD="/Library/LaunchDaemons/org.foldingathome.fahclient.plist"
13+
AGENT_PLIST="/Library/LaunchAgents/org.foldingathome.fah-screen-agent.plist"
1314

1415
if [ -f "$NEW_LAUNCHD" ]; then
1516
launchctl unload -w "$NEW_LAUNCHD" || true
@@ -23,6 +24,15 @@ if [ -f "$OLD_LAUNCHD" ]; then
2324
rm -f "$OLD_LAUNCHD" || true
2425
fi
2526

27+
if [ -f "$AGENT_PLIST" ]; then
28+
# stop agent running in console user's session and unload job
29+
conuser=$(/usr/bin/stat -f "%Su" /dev/console) || conuser="root"
30+
conuid=$(/usr/bin/id -u "$conuser") || conuid=0
31+
if [[ $conuid != 0 ]]; then
32+
launchctl bootout gui/$conuid "$AGENT_PLIST" || true
33+
fi
34+
fi
35+
2636
# Assuming upgrade, remove old stuff
2737
F1="/Applications/FAHClient.url"
2838
F2="/Applications/Folding@home/Web Control.url"

src/fah/client/osx/OSXOSImpl.cpp

Lines changed: 70 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
#include <pwd.h>
5050
#include <unistd.h>
5151

52+
#include <fah/screen-agent/defines.h>
53+
5254
using namespace FAH::Client;
5355
using namespace cb;
5456
using namespace std;
@@ -66,6 +68,9 @@ enum {
6668

6769

6870
namespace {
71+
CFStringRef kScreenIdle = CFSTR(SCREEN_IDLE_NOTIFICATION);
72+
CFStringRef kScreenNotIdle = CFSTR(SCREEN_NOT_IDLE_NOTIFICATION);
73+
6974
#pragma mark c callbacks
7075

7176
void consoleUserCB(SCDynamicStoreRef s, CFArrayRef keys, void *info) {
@@ -94,6 +99,17 @@ namespace {
9499
OSXOSImpl::instance().requestExit();
95100
}
96101

102+
void screenIdleCB(CFNotificationCenterRef center, void *observer,
103+
CFNotificationName name, const void *object,
104+
CFDictionaryRef info) {
105+
OSXOSImpl::instance().noteScreenIdle();
106+
}
107+
108+
void screenNotIdleCB(CFNotificationCenterRef center, void *observer,
109+
CFNotificationName name, const void *object,
110+
CFDictionaryRef info) {
111+
OSXOSImpl::instance().noteScreenNotIdle();
112+
}
97113
}
98114

99115

@@ -204,7 +220,7 @@ void OSXOSImpl::run() {
204220

205221

206222
void OSXOSImpl::finishInit() {
207-
LOG_DEBUG(5, "OSXOSImpl::finishInit() on thread " << pthread_self() <<
223+
LOG_DEBUG(5, "OSXOSImpl::finishInit() on thread " << pthread_self() <<
208224
(pthread_main_np() ? " main" : ""));
209225

210226
// Init display power state if registration succeeded
@@ -222,8 +238,10 @@ void OSXOSImpl::finishInit() {
222238

223239

224240
void OSXOSImpl::updateSystemIdle() {
225-
bool shouldBeIdle = displayPower == kDisplayPowerOff || loginwindowIsActive ||
226-
screensaverIsActive || screenIsLocked;
241+
bool shouldBeIdle;
242+
if (gotScreenNotIdleRecently()) shouldBeIdle = false;
243+
else shouldBeIdle = displayPower == kDisplayPowerOff || loginwindowIsActive ||
244+
gotScreenIdleRecently();
227245
if (shouldBeIdle == systemIsIdle) return;
228246
systemIsIdle = shouldBeIdle;
229247
event->activate();
@@ -483,6 +501,45 @@ bool OSXOSImpl::registerForConsoleUserNotifications() {
483501
}
484502

485503

504+
void OSXOSImpl::noteScreenIdle() {
505+
screenIdleExpiry =
506+
dispatch_time(DISPATCH_TIME_NOW, SCREEN_NOTIFICATION_EXPIRES * NSEC_PER_SEC);
507+
bool wasIdle = screenIdle;
508+
screenIdle = true;
509+
dispatch_after(screenIdleExpiry + NSEC_PER_SEC, dispatch_get_main_queue(), ^{
510+
updateSystemIdle();
511+
});
512+
if (!wasIdle) delayedUpdateSystemIdle(5);
513+
}
514+
515+
516+
void OSXOSImpl::noteScreenNotIdle() {
517+
screenNotIdleExpiry =
518+
dispatch_time(DISPATCH_TIME_NOW, SCREEN_NOTIFICATION_EXPIRES * NSEC_PER_SEC);
519+
screenNotIdle = true;
520+
dispatch_after(screenNotIdleExpiry + NSEC_PER_SEC,dispatch_get_main_queue(),^{
521+
updateSystemIdle();
522+
});
523+
updateSystemIdle();
524+
}
525+
526+
527+
bool OSXOSImpl::gotScreenIdleRecently() {
528+
if (!screenIdle) return false;
529+
if (dispatch_time(DISPATCH_TIME_NOW, 0) < screenIdleExpiry) return true;
530+
screenIdle = false;
531+
return false;
532+
}
533+
534+
535+
bool OSXOSImpl::gotScreenNotIdleRecently() {
536+
if (!screenNotIdle) return false;
537+
if (dispatch_time(DISPATCH_TIME_NOW, 0) < screenNotIdleExpiry) return true;
538+
screenNotIdle = false;
539+
return false;
540+
}
541+
542+
486543
bool OSXOSImpl::registerForDarwinNotifications() {
487544
CFNotificationCenterRef nc = CFNotificationCenterGetDarwinNotifyCenter();
488545

@@ -496,16 +553,18 @@ bool OSXOSImpl::registerForDarwinNotifications() {
496553
CFStringRef name =
497554
CFStringCreateWithCString(0, key.c_str(), kCFStringEncodingUTF8);
498555

499-
if (name) {
500-
CFNotificationCenterAddObserver(
501-
nc, (void *)this, &noteQuitCB, name, 0,
502-
CFNotificationSuspensionBehaviorCoalesce);
503-
CFRelease(name);
556+
if (!name) return false;
557+
CFNotificationCenterAddObserver(nc, (void *)this, &noteQuitCB,
558+
name, 0, CFNotificationSuspensionBehaviorCoalesce);
559+
CFRelease(name);
504560

505-
return true;
506-
}
561+
CFNotificationCenterAddObserver(nc, (void *)this, &screenIdleCB,
562+
kScreenIdle, 0, CFNotificationSuspensionBehaviorCoalesce);
507563

508-
return false;
564+
CFNotificationCenterAddObserver(nc, (void *)this, &screenNotIdleCB,
565+
kScreenNotIdle, 0, CFNotificationSuspensionBehaviorCoalesce);
566+
567+
return true;
509568
}
510569

511570

src/fah/client/osx/OSXOSImpl.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,15 @@ namespace FAH {
4646
static OSXOSImpl *singleton;
4747

4848
std::atomic<bool> systemIsIdle = false;
49-
bool screensaverIsActive = false;
50-
bool screenIsLocked = false;
49+
5150
bool loginwindowIsActive = false;
5251

52+
// these are notification received bools; both are needed
53+
bool screenIdle = false;
54+
bool screenNotIdle = false;
55+
dispatch_time_t screenIdleExpiry = 0;
56+
dispatch_time_t screenNotIdleExpiry = 0;
57+
5358
io_service_t displayWrangler = 0;
5459
IONotificationPortRef displayNotePort = 0;
5560
CFRunLoopSourceRef displayNoteSource = 0;
@@ -87,11 +92,15 @@ namespace FAH {
8792
(void *context, io_service_t service, natural_t mtype, void *marg);
8893
void finishInit();
8994
void updateTimerFired(CFRunLoopTimerRef timer, void *info);
95+
void noteScreenIdle();
96+
void noteScreenNotIdle();
9097

9198
protected:
9299
void initialize();
93100
void addHeartbeatTimerToRunLoop(CFRunLoopRef loop);
94101
bool registerForConsoleUserNotifications();
102+
bool gotScreenIdleRecently();
103+
bool gotScreenNotIdleRecently();
95104
bool registerForDarwinNotifications();
96105
bool registerForDisplayPowerNotifications();
97106
bool registerForLaunchEvents();

src/fah/screen-agent/defines.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/******************************************************************************\
2+
3+
This file is part of the Folding@home Client.
4+
5+
The fah-client runs Folding@home protein folding simulations.
6+
Copyright (c) 2001-2023, foldingathome.org
7+
All rights reserved.
8+
9+
This program is free software; you can redistribute it and/or modify
10+
it under the terms of the GNU General Public License as published by
11+
the Free Software Foundation; either version 3 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
GNU General Public License for more details.
18+
19+
You should have received a copy of the GNU General Public License along
20+
with this program; if not, write to the Free Software Foundation, Inc.,
21+
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22+
23+
For information regarding this software email:
24+
Joseph Coffland
25+
joseph@cauldrondevelopment.com
26+
27+
\******************************************************************************/
28+
29+
#pragma once
30+
31+
// Defines shared with fah-client
32+
33+
#define SCREEN_IDLE_NOTIFICATION "org.foldingathome.screen.idle"
34+
#define SCREEN_NOT_IDLE_NOTIFICATION "org.foldingathome.screen.notidle"
35+
36+
#define SCREEN_NOTIFICATION_INTERVAL 60
37+
#define SCREEN_NOTIFICATION_LEEWAY 2
38+
#define SCREEN_NOTIFICATION_EXPIRES (\
39+
SCREEN_NOTIFICATION_INTERVAL + 2 * SCREEN_NOTIFICATION_LEEWAY + 1)

0 commit comments

Comments
 (0)