00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #import "COSXScreenSaver.h"
00016 #import "COSXScreenSaverUtil.h"
00017 #import "CLog.h"
00018 #import "IEventQueue.h"
00019 #import "IPrimaryScreen.h"
00020 #import <string.h>
00021
00022
00023
00024
00025
00026 COSXScreenSaver::COSXScreenSaver(void* eventTarget) :
00027 m_eventTarget(eventTarget),
00028 m_enabled(true)
00029 {
00030 m_autoReleasePool = screenSaverUtilCreatePool();
00031 m_screenSaverController = screenSaverUtilCreateController();
00032
00033
00034 EventTypeSpec launchEventTypes[2];
00035 launchEventTypes[0].eventClass = kEventClassApplication;
00036 launchEventTypes[0].eventKind = kEventAppLaunched;
00037 launchEventTypes[1].eventClass = kEventClassApplication;
00038 launchEventTypes[1].eventKind = kEventAppTerminated;
00039
00040 EventHandlerUPP launchTerminationEventHandler =
00041 NewEventHandlerUPP(launchTerminationCallback);
00042 InstallApplicationEventHandler(launchTerminationEventHandler, 2,
00043 launchEventTypes, this,
00044 &m_launchTerminationEventHandlerRef);
00045 DisposeEventHandlerUPP(launchTerminationEventHandler);
00046
00047 m_screenSaverPSN.highLongOfPSN = 0;
00048 m_screenSaverPSN.lowLongOfPSN = 0;
00049
00050
00051 if (isActive()) {
00052 ProcessInfoRec procInfo;
00053 Str31 procName;
00054 memset(&procInfo, 0, sizeof(procInfo));
00055 procInfo.processName = procName;
00056 procInfo.processInfoLength = sizeof(ProcessInfoRec);
00057
00058 ProcessSerialNumber psn;
00059 OSErr err = GetNextProcess(&psn);
00060 while (err == 0) {
00061 memset(procName, 0, sizeof(procName));
00062 err = GetProcessInformation(&psn, &procInfo);
00063 if (err != 0) {
00064 break;
00065 }
00066 if (strcmp("ScreenSaverEngine", (const char*)&procName[1]) == 0) {
00067 m_screenSaverPSN = psn;
00068 break;
00069 }
00070 err = GetNextProcess(&psn);
00071 }
00072 }
00073 }
00074
00075 COSXScreenSaver::~COSXScreenSaver()
00076 {
00077 RemoveEventHandler(m_launchTerminationEventHandlerRef);
00078
00079 screenSaverUtilReleasePool(m_autoReleasePool);
00080 }
00081
00082 void
00083 COSXScreenSaver::enable()
00084 {
00085 m_enabled = true;
00086 screenSaverUtilEnable(m_screenSaverController);
00087 }
00088
00089 void
00090 COSXScreenSaver::disable()
00091 {
00092 m_enabled = false;
00093 screenSaverUtilDisable(m_screenSaverController);
00094 }
00095
00096 void
00097 COSXScreenSaver::activate()
00098 {
00099 screenSaverUtilActivate(m_screenSaverController);
00100 }
00101
00102 void
00103 COSXScreenSaver::deactivate()
00104 {
00105 screenSaverUtilDeactivate(m_screenSaverController, m_enabled);
00106 }
00107
00108 bool
00109 COSXScreenSaver::isActive() const
00110 {
00111 return (screenSaverUtilIsActive(m_screenSaverController) != 0);
00112 }
00113
00114 void
00115 COSXScreenSaver::processLaunched(ProcessSerialNumber psn)
00116 {
00117 CFStringRef processName;
00118 OSStatus err = CopyProcessName(&psn, &processName);
00119
00120 if (err == 0 && CFEqual(CFSTR("ScreenSaverEngine"), processName)) {
00121 m_screenSaverPSN = psn;
00122 LOG((CLOG_DEBUG1 "ScreenSaverEngine launched. Enabled=%d", m_enabled));
00123 if (m_enabled) {
00124 EVENTQUEUE->addEvent(
00125 CEvent(IPrimaryScreen::getScreensaverActivatedEvent(),
00126 m_eventTarget));
00127 }
00128 }
00129 }
00130
00131 void
00132 COSXScreenSaver::processTerminated(ProcessSerialNumber psn)
00133 {
00134 if (m_screenSaverPSN.highLongOfPSN == psn.highLongOfPSN &&
00135 m_screenSaverPSN.lowLongOfPSN == psn.lowLongOfPSN) {
00136 LOG((CLOG_DEBUG1 "ScreenSaverEngine terminated. Enabled=%d", m_enabled));
00137 if (m_enabled) {
00138 EVENTQUEUE->addEvent(
00139 CEvent(IPrimaryScreen::getScreensaverDeactivatedEvent(),
00140 m_eventTarget));
00141 }
00142
00143 m_screenSaverPSN.highLongOfPSN = 0;
00144 m_screenSaverPSN.lowLongOfPSN = 0;
00145 }
00146 }
00147
00148 pascal OSStatus
00149 COSXScreenSaver::launchTerminationCallback(
00150 EventHandlerCallRef nextHandler,
00151 EventRef theEvent, void* userData)
00152 {
00153 OSStatus result;
00154 ProcessSerialNumber psn;
00155 EventParamType actualType;
00156 UInt32 actualSize;
00157
00158 result = GetEventParameter(theEvent, kEventParamProcessID,
00159 typeProcessSerialNumber, &actualType,
00160 sizeof(psn), &actualSize, &psn);
00161
00162 if ((result == noErr) &&
00163 (actualSize > 0) &&
00164 (actualType == typeProcessSerialNumber)) {
00165 COSXScreenSaver* screenSaver = (COSXScreenSaver*)userData;
00166 UInt32 eventKind = GetEventKind(theEvent);
00167 if (eventKind == kEventAppLaunched) {
00168 screenSaver->processLaunched(psn);
00169 }
00170 else if (eventKind == kEventAppTerminated) {
00171 screenSaver->processTerminated(psn);
00172 }
00173 }
00174 return (CallNextEventHandler(nextHandler, theEvent));
00175 }