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 fWindow->ChildAt(0)->SetViewColor(0, 0, 0); 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 fWindow->Sync(); 124 // TODO: is that needed? 125 ShowCursor(); 126 if (fPasswordWindow->IsHidden()) 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, "suspend 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 { 231 if (fWindow->Lock()) { 232 HideCursor(); 233 fPasswordWindow->SetPassword(""); 234 fPasswordWindow->Hide(); 235 236 fRunner->Resume(); 237 fWindow->Unlock(); 238 } 239 240 // Turn on the message filter again 241 BMessage enable(kMsgEnableFilter); 242 fWindow->PostMessage(&enable); 243 244 _QueueTurnOffScreen(); 245 break; 246 } 247 248 case kMsgTurnOffScreen: 249 _SetDPMSMode(B_DPMS_OFF); 250 break; 251 case kMsgSuspendScreen: 252 _SetDPMSMode(B_DPMS_SUSPEND); 253 break; 254 case kMsgStandByScreen: 255 _SetDPMSMode(B_DPMS_STAND_BY); 256 break; 257 258 default: 259 BApplication::MessageReceived(message); 260 break; 261 } 262 } 263 264 265 bool 266 ScreenBlanker::QuitRequested() 267 { 268 if (fSettings.LockEnable() 269 && system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) { 270 _ShowPasswordWindow(); 271 return false; 272 } 273 274 _Shutdown(); 275 return true; 276 } 277 278 279 void 280 ScreenBlanker::_Shutdown() 281 { 282 if (fWindow) { 283 fWindow->Hide(); 284 285 if (fWindow->Lock()) 286 fWindow->Quit(); 287 } 288 289 delete fRunner; 290 } 291 292 293 // #pragma mark - 294 295 296 int 297 main(int, char**) 298 { 299 ScreenBlanker app; 300 app.Run(); 301 return 0; 302 } 303