1 /* 2 * Copyright 2003-2006, 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_SUSPEND; 177 if (fSettings.SuspendTime() == fSettings.StandByTime()) 178 flags &= ENABLE_DPMS_STAND_BY; 179 180 // start them off again 181 182 if (flags & ENABLE_DPMS_STAND_BY) { 183 BMessage dpms(kMsgStandByScreen); 184 fStandByScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 185 fSettings.StandByTime(), 1); 186 if (fStandByScreenRunner->InitCheck() != B_OK) 187 syslog(LOG_ERR, "standby screen saver runner failed\n"); 188 } 189 190 if (flags & ENABLE_DPMS_SUSPEND) { 191 BMessage dpms(kMsgSuspendScreen); 192 fSuspendScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 193 fSettings.SuspendTime(), 1); 194 if (fSuspendScreenRunner->InitCheck() != B_OK) 195 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 196 } 197 198 if (flags & ENABLE_DPMS_OFF) { 199 BMessage dpms(kMsgTurnOffScreen); 200 fTurnOffScreenRunner = new BMessageRunner(BMessenger(this), &dpms, 201 fSettings.OffTime(), 1); 202 if (fTurnOffScreenRunner->InitCheck() != B_OK) 203 syslog(LOG_ERR, "turn off screen saver runner failed\n"); 204 } 205 } 206 207 208 void 209 ScreenBlanker::MessageReceived(BMessage* message) 210 { 211 switch (message->what) { 212 case kMsgUnlock: 213 { 214 if (strcmp(fSettings.Password(), crypt(fPasswordWindow->Password(), 215 fSettings.Password())) != 0) { 216 beep(); 217 fPasswordWindow->SetPassword(""); 218 _QueueResumeScreenSaver(); 219 } else { 220 PRINT(("Quitting!\n")); 221 _Shutdown(); 222 Quit(); 223 } 224 break; 225 } 226 227 case kMsgResumeSaver: 228 if (fWindow->Lock()) { 229 if (fWindow->SetFullScreen(true) == B_OK) { 230 HideCursor(); 231 fPasswordWindow->Hide(); 232 } 233 234 fRunner->Resume(); 235 fWindow->Unlock(); 236 } 237 238 _QueueTurnOffScreen(); 239 break; 240 241 case kMsgTurnOffScreen: 242 _SetDPMSMode(B_DPMS_OFF); 243 break; 244 case kMsgSuspendScreen: 245 _SetDPMSMode(B_DPMS_SUSPEND); 246 break; 247 case kMsgStandByScreen: 248 _SetDPMSMode(B_DPMS_STAND_BY); 249 break; 250 251 default: 252 BApplication::MessageReceived(message); 253 break; 254 } 255 } 256 257 258 bool 259 ScreenBlanker::QuitRequested() 260 { 261 if (fSettings.LockEnable() 262 && system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) { 263 _ShowPasswordWindow(); 264 return false; 265 } 266 267 _Shutdown(); 268 return true; 269 } 270 271 272 void 273 ScreenBlanker::_Shutdown() 274 { 275 delete fRunner; 276 277 if (fWindow) { 278 fWindow->Hide(); 279 280 if (fWindow->Lock()) 281 fWindow->Quit(); 282 } 283 } 284 285 286 // #pragma mark - 287 288 289 int 290 main(int, char**) 291 { 292 ScreenBlanker app; 293 app.Run(); 294 return 0; 295 } 296