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