1 /* 2 * Copyright 2003-2007, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Michael Phipps 7 * Jérôme Duval, jerome.duval@free.fr 8 * Axel Dörfler, axeld@pinc-software.de 9 */ 10 11 12 #include "ScreenBlanker.h" 13 14 #include <Beep.h> 15 #include <Debug.h> 16 #include <File.h> 17 #include <FindDirectory.h> 18 #include <Path.h> 19 #include <Screen.h> 20 #include <StorageDefs.h> 21 #include <SupportDefs.h> 22 #include <image.h> 23 24 #include <stdio.h> 25 #include <string.h> 26 #include <syslog.h> 27 28 29 const static uint32 kMsgResumeSaver = 'RSSV'; 30 const static uint32 kMsgTurnOffScreen = 'tofs'; 31 const static uint32 kMsgSuspendScreen = 'suss'; 32 const static uint32 kMsgStandByScreen = 'stbs'; 33 34 35 ScreenBlanker::ScreenBlanker() 36 : BApplication(SCREEN_BLANKER_SIG), 37 fWindow(NULL), 38 fSaver(NULL), 39 fRunner(NULL), 40 fPasswordWindow(NULL), 41 fResumeRunner(NULL), 42 fStandByScreenRunner(NULL), 43 fSuspendScreenRunner(NULL), 44 fTurnOffScreenRunner(NULL) 45 { 46 fBlankTime = system_time(); 47 } 48 49 50 ScreenBlanker::~ScreenBlanker() 51 { 52 delete fResumeRunner; 53 _TurnOnScreen(); 54 } 55 56 57 void 58 ScreenBlanker::ReadyToRun() 59 { 60 if (!fSettings.Load()) { 61 fprintf(stderr, "could not load settings\n"); 62 exit(1); 63 } 64 65 // create a BDirectWindow and start the render thread. 66 // TODO: we need a window per screen... 67 BScreen screen(B_MAIN_SCREEN_ID); 68 fWindow = new ScreenSaverWindow(screen.Frame()); 69 fPasswordWindow = new PasswordWindow(); 70 fRunner = new ScreenSaverRunner(fWindow, fWindow->ChildAt(0), false, fSettings); 71 72 fSaver = fRunner->ScreenSaver(); 73 if (fSaver) { 74 fWindow->SetSaver(fSaver); 75 fRunner->Run(); 76 } else { 77 fprintf(stderr, "could not load the screensaver addon\n"); 78 } 79 80 fWindow->SetFullScreen(true); 81 fWindow->Show(); 82 HideCursor(); 83 84 _QueueTurnOffScreen(); 85 } 86 87 88 void 89 ScreenBlanker::_TurnOnScreen() 90 { 91 delete fStandByScreenRunner; 92 delete fSuspendScreenRunner; 93 delete fTurnOffScreenRunner; 94 95 fStandByScreenRunner = fSuspendScreenRunner = fTurnOffScreenRunner = NULL; 96 97 BScreen screen; 98 screen.SetDPMS(B_DPMS_ON); 99 } 100 101 102 void 103 ScreenBlanker::_SetDPMSMode(uint32 mode) 104 { 105 BScreen screen; 106 screen.SetDPMS(mode); 107 108 if (fWindow->Lock()) { 109 fRunner->Suspend(); 110 fWindow->Unlock(); 111 } 112 } 113 114 115 void 116 ScreenBlanker::_ShowPasswordWindow() 117 { 118 _TurnOnScreen(); 119 120 if (fWindow->Lock()) { 121 fRunner->Suspend(); 122 123 fWindow->Sync(); 124 // TODO: is that needed? 125 ShowCursor(); 126 fPasswordWindow->Show(); 127 128 fWindow->Unlock(); 129 } 130 131 _QueueResumeScreenSaver(); 132 } 133 134 135 void 136 ScreenBlanker::_QueueResumeScreenSaver() 137 { 138 delete fResumeRunner; 139 140 BMessage resume(kMsgResumeSaver); 141 fResumeRunner = new BMessageRunner(BMessenger(this), &resume, 142 fSettings.BlankTime(), 1); 143 if (fResumeRunner->InitCheck() != B_OK) 144 syslog(LOG_ERR, "resume screen saver runner failed\n"); 145 } 146 147 148 void 149 ScreenBlanker::_QueueTurnOffScreen() 150 { 151 // stop running notifiers 152 153 delete fStandByScreenRunner; 154 delete fSuspendScreenRunner; 155 delete fTurnOffScreenRunner; 156 157 fStandByScreenRunner = fSuspendScreenRunner = fTurnOffScreenRunner = NULL; 158 159 // figure out which notifiers we need and which of them are supported 160 161 uint32 flags = fSettings.TimeFlags(); 162 BScreen screen; 163 uint32 capabilities = screen.DPMSCapabilites(); 164 if ((capabilities & B_DPMS_OFF) == 0) 165 flags &= ~ENABLE_DPMS_OFF; 166 if ((capabilities & B_DPMS_SUSPEND) == 0) 167 flags &= ~ENABLE_DPMS_SUSPEND; 168 if ((capabilities & B_DPMS_STAND_BY) == 0) 169 flags &= ~ENABLE_DPMS_STAND_BY; 170 171 if ((flags & ENABLE_DPMS_MASK) == 0) 172 return; 173 174 if (fSettings.OffTime() == fSettings.SuspendTime() 175 && (flags & (ENABLE_DPMS_OFF | ENABLE_DPMS_SUSPEND)) == ENABLE_DPMS_OFF | ENABLE_DPMS_SUSPEND) 176 flags &= ~ENABLE_DPMS_SUSPEND; 177 if (fSettings.SuspendTime() == fSettings.StandByTime() 178 && (flags & (ENABLE_DPMS_SUSPEND | ENABLE_DPMS_STAND_BY)) == ENABLE_DPMS_SUSPEND | ENABLE_DPMS_STAND_BY) 179 flags &= ~ENABLE_DPMS_STAND_BY; 180 181 // start them off again 182 183 if (flags & ENABLE_DPMS_STAND_BY) { 184 BMessage dpms(kMsgStandByScreen); 185 fStandByScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 186 fSettings.StandByTime(), 1); 187 if (fStandByScreenRunner->InitCheck() != B_OK) 188 syslog(LOG_ERR, "standby screen saver runner failed\n"); 189 } 190 191 if (flags & ENABLE_DPMS_SUSPEND) { 192 BMessage dpms(kMsgSuspendScreen); 193 fSuspendScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 194 fSettings.SuspendTime(), 1); 195 if (fSuspendScreenRunner->InitCheck() != B_OK) 196 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 197 } 198 199 if (flags & ENABLE_DPMS_OFF) { 200 BMessage dpms(kMsgTurnOffScreen); 201 fTurnOffScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 202 fSettings.OffTime(), 1); 203 if (fTurnOffScreenRunner->InitCheck() != B_OK) 204 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 205 } 206 } 207 208 209 void 210 ScreenBlanker::MessageReceived(BMessage* message) 211 { 212 switch (message->what) { 213 case kMsgUnlock: 214 { 215 if (strcmp(fSettings.Password(), crypt(fPasswordWindow->Password(), 216 fSettings.Password())) != 0) { 217 beep(); 218 fPasswordWindow->SetPassword(""); 219 _QueueResumeScreenSaver(); 220 } else { 221 PRINT(("Quitting!\n")); 222 _Shutdown(); 223 Quit(); 224 } 225 break; 226 } 227 228 case kMsgResumeSaver: 229 if (fWindow->Lock()) { 230 HideCursor(); 231 fPasswordWindow->Hide(); 232 233 fRunner->Resume(); 234 fWindow->Unlock(); 235 } 236 237 _QueueTurnOffScreen(); 238 break; 239 240 case kMsgTurnOffScreen: 241 _SetDPMSMode(B_DPMS_OFF); 242 break; 243 case kMsgSuspendScreen: 244 _SetDPMSMode(B_DPMS_SUSPEND); 245 break; 246 case kMsgStandByScreen: 247 _SetDPMSMode(B_DPMS_STAND_BY); 248 break; 249 250 default: 251 BApplication::MessageReceived(message); 252 break; 253 } 254 } 255 256 257 bool 258 ScreenBlanker::QuitRequested() 259 { 260 if (fSettings.LockEnable() 261 && system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) { 262 _ShowPasswordWindow(); 263 return false; 264 } 265 266 _Shutdown(); 267 return true; 268 } 269 270 271 void 272 ScreenBlanker::_Shutdown() 273 { 274 delete fRunner; 275 276 if (fWindow) { 277 fWindow->Hide(); 278 279 if (fWindow->Lock()) 280 fWindow->Quit(); 281 } 282 } 283 284 285 // #pragma mark - 286 287 288 int 289 main(int, char**) 290 { 291 ScreenBlanker app; 292 app.Run(); 293 return 0; 294 } 295