/* * 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 . */ #import "platform/OSXScreenSaver.h" #import "platform/OSXScreenSaverUtil.h" #import "barrier/IPrimaryScreen.h" #import "base/Log.h" #import "base/IEventQueue.h" #import #import // 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"