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