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 if (fWindow->SetFullScreen(false) == B_OK) { 124 fWindow->Sync(); 125 // TODO: is that needed? 126 ShowCursor(); 127 fPasswordWindow->Show(); 128 } 129 fWindow->Unlock(); 130 } 131 132 _QueueResumeScreenSaver(); 133 } 134 135 136 void 137 ScreenBlanker::_QueueResumeScreenSaver() 138 { 139 delete fResumeRunner; 140 141 BMessage resume(kMsgResumeSaver); 142 fResumeRunner = new BMessageRunner(BMessenger(this), &resume, 143 fSettings.BlankTime(), 1); 144 if (fResumeRunner->InitCheck() != B_OK) 145 syslog(LOG_ERR, "resume screen saver runner failed\n"); 146 } 147 148 149 void 150 ScreenBlanker::_QueueTurnOffScreen() 151 { 152 // stop running notifiers 153 154 delete fStandByScreenRunner; 155 delete fSuspendScreenRunner; 156 delete fTurnOffScreenRunner; 157 158 fStandByScreenRunner = fSuspendScreenRunner = fTurnOffScreenRunner = NULL; 159 160 // figure out which notifiers we need and which of them are supported 161 162 uint32 flags = fSettings.TimeFlags(); 163 BScreen screen; 164 uint32 capabilities = screen.DPMSCapabilites(); 165 if ((capabilities & B_DPMS_OFF) == 0) 166 flags &= ~ENABLE_DPMS_OFF; 167 if ((capabilities & B_DPMS_SUSPEND) == 0) 168 flags &= ~ENABLE_DPMS_SUSPEND; 169 if ((capabilities & B_DPMS_STAND_BY) == 0) 170 flags &= ~ENABLE_DPMS_STAND_BY; 171 172 if ((flags & ENABLE_DPMS_MASK) == 0) 173 return; 174 175 if (fSettings.OffTime() == fSettings.SuspendTime() 176 && (flags & (ENABLE_DPMS_OFF | ENABLE_DPMS_SUSPEND)) == ENABLE_DPMS_OFF | ENABLE_DPMS_SUSPEND) 177 flags &= ~ENABLE_DPMS_SUSPEND; 178 if (fSettings.SuspendTime() == fSettings.StandByTime() 179 && (flags & (ENABLE_DPMS_SUSPEND | ENABLE_DPMS_STAND_BY)) == ENABLE_DPMS_SUSPEND | ENABLE_DPMS_STAND_BY) 180 flags &= ~ENABLE_DPMS_STAND_BY; 181 182 // start them off again 183 184 if (flags & ENABLE_DPMS_STAND_BY) { 185 BMessage dpms(kMsgStandByScreen); 186 fStandByScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 187 fSettings.StandByTime(), 1); 188 if (fStandByScreenRunner->InitCheck() != B_OK) 189 syslog(LOG_ERR, "standby screen saver runner failed\n"); 190 } 191 192 if (flags & ENABLE_DPMS_SUSPEND) { 193 BMessage dpms(kMsgSuspendScreen); 194 fSuspendScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 195 fSettings.SuspendTime(), 1); 196 if (fSuspendScreenRunner->InitCheck() != B_OK) 197 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 198 } 199 200 if (flags & ENABLE_DPMS_OFF) { 201 BMessage dpms(kMsgTurnOffScreen); 202 fTurnOffScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 203 fSettings.OffTime(), 1); 204 if (fTurnOffScreenRunner->InitCheck() != B_OK) 205 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 206 } 207 } 208 209 210 void 211 ScreenBlanker::MessageReceived(BMessage* message) 212 { 213 switch (message->what) { 214 case kMsgUnlock: 215 { 216 if (strcmp(fSettings.Password(), crypt(fPasswordWindow->Password(), 217 fSettings.Password())) != 0) { 218 beep(); 219 fPasswordWindow->SetPassword(""); 220 _QueueResumeScreenSaver(); 221 } else { 222 PRINT(("Quitting!\n")); 223 _Shutdown(); 224 Quit(); 225 } 226 break; 227 } 228 229 case kMsgResumeSaver: 230 if (fWindow->Lock()) { 231 if (fWindow->SetFullScreen(true) == B_OK) { 232 HideCursor(); 233 fPasswordWindow->Hide(); 234 } 235 236 fRunner->Resume(); 237 fWindow->Unlock(); 238 } 239 240 _QueueTurnOffScreen(); 241 break; 242 243 case kMsgTurnOffScreen: 244 _SetDPMSMode(B_DPMS_OFF); 245 break; 246 case kMsgSuspendScreen: 247 _SetDPMSMode(B_DPMS_SUSPEND); 248 break; 249 case kMsgStandByScreen: 250 _SetDPMSMode(B_DPMS_STAND_BY); 251 break; 252 253 default: 254 BApplication::MessageReceived(message); 255 break; 256 } 257 } 258 259 260 bool 261 ScreenBlanker::QuitRequested() 262 { 263 if (fSettings.LockEnable() 264 && system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) { 265 _ShowPasswordWindow(); 266 return false; 267 } 268 269 _Shutdown(); 270 return true; 271 } 272 273 274 void 275 ScreenBlanker::_Shutdown() 276 { 277 delete fRunner; 278 279 if (fWindow) { 280 fWindow->Hide(); 281 282 if (fWindow->Lock()) 283 fWindow->Quit(); 284 } 285 } 286 287 288 // #pragma mark - 289 290 291 int 292 main(int, char**) 293 { 294 ScreenBlanker app; 295 app.Run(); 296 return 0; 297 } 298