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