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