diff options
Diffstat (limited to 'src/lib/platform/OSXScreenSaver.cpp')
| -rw-r--r-- | src/lib/platform/OSXScreenSaver.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/src/lib/platform/OSXScreenSaver.cpp b/src/lib/platform/OSXScreenSaver.cpp new file mode 100644 index 0000000..a0282d9 --- /dev/null +++ b/src/lib/platform/OSXScreenSaver.cpp @@ -0,0 +1,201 @@ +/* + * barrier -- mouse and keyboard sharing utility + * Copyright (C) 2012-2016 Symless Ltd. + * Copyright (C) 2004 Chris Schoeneman + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file LICENSE that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#import "platform/OSXScreenSaver.h" + +#import "platform/OSXScreenSaverUtil.h" +#import "barrier/IPrimaryScreen.h" +#import "base/Log.h" +#import "base/IEventQueue.h" + +#import <string.h> +#import <sys/sysctl.h> + +// TODO: upgrade deprecated function usage in these functions. +void getProcessSerialNumber(const char* name, ProcessSerialNumber& psn); +bool testProcessName(const char* name, const ProcessSerialNumber& psn); + +// +// OSXScreenSaver +// + +OSXScreenSaver::OSXScreenSaver(IEventQueue* events, void* eventTarget) : + m_eventTarget(eventTarget), + m_enabled(true), + m_events(events) +{ + m_autoReleasePool = screenSaverUtilCreatePool(); + m_screenSaverController = screenSaverUtilCreateController(); + + // install launch/termination event handlers + EventTypeSpec launchEventTypes[2]; + launchEventTypes[0].eventClass = kEventClassApplication; + launchEventTypes[0].eventKind = kEventAppLaunched; + launchEventTypes[1].eventClass = kEventClassApplication; + launchEventTypes[1].eventKind = kEventAppTerminated; + + EventHandlerUPP launchTerminationEventHandler = + NewEventHandlerUPP(launchTerminationCallback); + InstallApplicationEventHandler(launchTerminationEventHandler, 2, + launchEventTypes, this, + &m_launchTerminationEventHandlerRef); + DisposeEventHandlerUPP(launchTerminationEventHandler); + + m_screenSaverPSN.highLongOfPSN = 0; + m_screenSaverPSN.lowLongOfPSN = 0; + + if (isActive()) { + getProcessSerialNumber("ScreenSaverEngine", m_screenSaverPSN); + } +} + +OSXScreenSaver::~OSXScreenSaver() +{ + RemoveEventHandler(m_launchTerminationEventHandlerRef); +// screenSaverUtilReleaseController(m_screenSaverController); + screenSaverUtilReleasePool(m_autoReleasePool); +} + +void +OSXScreenSaver::enable() +{ + m_enabled = true; + screenSaverUtilEnable(m_screenSaverController); +} + +void +OSXScreenSaver::disable() +{ + m_enabled = false; + screenSaverUtilDisable(m_screenSaverController); +} + +void +OSXScreenSaver::activate() +{ + screenSaverUtilActivate(m_screenSaverController); +} + +void +OSXScreenSaver::deactivate() +{ + screenSaverUtilDeactivate(m_screenSaverController, m_enabled); +} + +bool +OSXScreenSaver::isActive() const +{ + return (screenSaverUtilIsActive(m_screenSaverController) != 0); +} + +void +OSXScreenSaver::processLaunched(ProcessSerialNumber psn) +{ + if (testProcessName("ScreenSaverEngine", psn)) { + m_screenSaverPSN = psn; + LOG((CLOG_DEBUG1 "ScreenSaverEngine launched. Enabled=%d", m_enabled)); + if (m_enabled) { + m_events->addEvent( + Event(m_events->forIPrimaryScreen().screensaverActivated(), + m_eventTarget)); + } + } +} + +void +OSXScreenSaver::processTerminated(ProcessSerialNumber psn) +{ + if (m_screenSaverPSN.highLongOfPSN == psn.highLongOfPSN && + m_screenSaverPSN.lowLongOfPSN == psn.lowLongOfPSN) { + LOG((CLOG_DEBUG1 "ScreenSaverEngine terminated. Enabled=%d", m_enabled)); + if (m_enabled) { + m_events->addEvent( + Event(m_events->forIPrimaryScreen().screensaverDeactivated(), + m_eventTarget)); + } + + m_screenSaverPSN.highLongOfPSN = 0; + m_screenSaverPSN.lowLongOfPSN = 0; + } +} + +pascal OSStatus +OSXScreenSaver::launchTerminationCallback( + EventHandlerCallRef nextHandler, + EventRef theEvent, void* userData) +{ + OSStatus result; + ProcessSerialNumber psn; + EventParamType actualType; + ByteCount actualSize; + + result = GetEventParameter(theEvent, kEventParamProcessID, + typeProcessSerialNumber, &actualType, + sizeof(psn), &actualSize, &psn); + + if ((result == noErr) && + (actualSize > 0) && + (actualType == typeProcessSerialNumber)) { + OSXScreenSaver* screenSaver = (OSXScreenSaver*)userData; + UInt32 eventKind = GetEventKind(theEvent); + if (eventKind == kEventAppLaunched) { + screenSaver->processLaunched(psn); + } + else if (eventKind == kEventAppTerminated) { + screenSaver->processTerminated(psn); + } + } + return (CallNextEventHandler(nextHandler, theEvent)); +} + +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +void +getProcessSerialNumber(const char* name, ProcessSerialNumber& psn) +{ + ProcessInfoRec procInfo; + Str31 procName; // pascal string. first byte holds length. + memset(&procInfo, 0, sizeof(procInfo)); + procInfo.processName = procName; + procInfo.processInfoLength = sizeof(ProcessInfoRec); + + ProcessSerialNumber checkPsn; + OSErr err = GetNextProcess(&checkPsn); + while (err == 0) { + memset(procName, 0, sizeof(procName)); + err = GetProcessInformation(&checkPsn, &procInfo); + if (err != 0) { + break; + } + if (strcmp(name, (const char*)&procName[1]) == 0) { + psn = checkPsn; + break; + } + err = GetNextProcess(&checkPsn); + } +} + +bool +testProcessName(const char* name, const ProcessSerialNumber& psn) +{ + CFStringRef processName; + OSStatus err = CopyProcessName(&psn, &processName); + return (err == 0 && CFEqual(CFSTR("ScreenSaverEngine"), processName)); +} + +#pragma GCC diagnostic error "-Wdeprecated-declarations" |
