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