1 /* 2 * Copyright 2003-2009, 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 * Ryan Leavengood, leavengood@gmail.com 10 */ 11 12 13 #include "ScreenBlanker.h" 14 15 #include <Beep.h> 16 #include <Debug.h> 17 #include <File.h> 18 #include <FindDirectory.h> 19 #include <Path.h> 20 #include <Screen.h> 21 #include <StorageDefs.h> 22 #include <SupportDefs.h> 23 #include <image.h> 24 25 #include <stdio.h> 26 #include <string.h> 27 #include <syslog.h> 28 29 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, using defaults\n"); 62 } 63 64 // create a BDirectWindow and start the render thread. 65 // TODO: we need a window per screen... 66 BScreen screen(B_MAIN_SCREEN_ID); 67 fWindow = new ScreenSaverWindow(screen.Frame()); 68 fPasswordWindow = new PasswordWindow(); 69 fRunner = new ScreenSaverRunner(fWindow, fWindow->ChildAt(0), false, fSettings); 70 71 fSaver = fRunner->ScreenSaver(); 72 if (fSaver) { 73 fWindow->SetSaver(fSaver); 74 fRunner->Run(); 75 } else { 76 fprintf(stderr, "could not load the screensaver addon\n"); 77 } 78 79 fWindow->SetFullScreen(true); 80 fWindow->Show(); 81 HideCursor(); 82 83 _QueueTurnOffScreen(); 84 } 85 86 87 void 88 ScreenBlanker::_TurnOnScreen() 89 { 90 delete fStandByScreenRunner; 91 delete fSuspendScreenRunner; 92 delete fTurnOffScreenRunner; 93 94 fStandByScreenRunner = fSuspendScreenRunner = fTurnOffScreenRunner = NULL; 95 96 BScreen screen; 97 screen.SetDPMS(B_DPMS_ON); 98 } 99 100 101 void 102 ScreenBlanker::_SetDPMSMode(uint32 mode) 103 { 104 BScreen screen; 105 screen.SetDPMS(mode); 106 107 if (fWindow->Lock()) { 108 fRunner->Suspend(); 109 fWindow->Unlock(); 110 } 111 } 112 113 114 void 115 ScreenBlanker::_ShowPasswordWindow() 116 { 117 _TurnOnScreen(); 118 119 if (fWindow->Lock()) { 120 fRunner->Suspend(); 121 122 fWindow->Sync(); 123 // TODO: is that needed? 124 ShowCursor(); 125 if (fPasswordWindow->IsHidden()) 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, "suspend 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 { 230 if (fWindow->Lock()) { 231 HideCursor(); 232 fPasswordWindow->SetPassword(""); 233 fPasswordWindow->Hide(); 234 235 fRunner->Resume(); 236 fWindow->Unlock(); 237 } 238 239 // Turn on the message filter again 240 BMessage enable(kMsgEnableFilter); 241 fWindow->PostMessage(&enable); 242 243 _QueueTurnOffScreen(); 244 break; 245 } 246 247 case kMsgTurnOffScreen: 248 _SetDPMSMode(B_DPMS_OFF); 249 break; 250 case kMsgSuspendScreen: 251 _SetDPMSMode(B_DPMS_SUSPEND); 252 break; 253 case kMsgStandByScreen: 254 _SetDPMSMode(B_DPMS_STAND_BY); 255 break; 256 257 default: 258 BApplication::MessageReceived(message); 259 break; 260 } 261 } 262 263 264 bool 265 ScreenBlanker::QuitRequested() 266 { 267 if (fSettings.LockEnable() 268 && system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) { 269 _ShowPasswordWindow(); 270 return false; 271 } 272 273 _Shutdown(); 274 return true; 275 } 276 277 278 void 279 ScreenBlanker::_Shutdown() 280 { 281 if (fWindow) { 282 fWindow->Hide(); 283 284 if (fWindow->Lock()) 285 fWindow->Quit(); 286 } 287 288 delete fRunner; 289 } 290 291 292 // #pragma mark - 293 294 295 int 296 main(int, char**) 297 { 298 ScreenBlanker app; 299 app.Run(); 300 return 0; 301 } 302