xref: /haiku/src/bin/screen_blanker/ScreenBlanker.cpp (revision e711e6e42fd7ec3111ba9dc2324fa8efedd6674b)
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 
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 
57 ScreenBlanker::~ScreenBlanker()
58 {
59 	delete fResumeRunner;
60 	_TurnOnScreen();
61 }
62 
63 
64 void
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
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
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
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
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
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
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
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
300 ScreenBlanker::IsPasswordWindowShown() const
301 {
302 	return fPasswordWindow != NULL && !fPasswordWindow->IsHidden();
303 }
304 
305 
306 void
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
325 main(int argc, char** argv)
326 {
327 	ScreenBlanker app;
328 	app.Run();
329 
330 	return 0;
331 }
332