xref: /haiku/src/bin/screen_blanker/ScreenBlanker.cpp (revision be3db2942c0e8dda63cdd226ec3c99309d3eab0c)
1 /*
2  * Copyright 2003-2007, 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  */
10 
11 
12 #include "ScreenBlanker.h"
13 
14 #include <Beep.h>
15 #include <Debug.h>
16 #include <File.h>
17 #include <FindDirectory.h>
18 #include <Path.h>
19 #include <Screen.h>
20 #include <StorageDefs.h>
21 #include <SupportDefs.h>
22 #include <image.h>
23 
24 #include <stdio.h>
25 #include <string.h>
26 #include <syslog.h>
27 
28 
29 const static uint32 kMsgResumeSaver = 'RSSV';
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\n");
62 		exit(1);
63 	}
64 
65 	// create a BDirectWindow and start the render thread.
66 	// TODO: we need a window per screen...
67 	BScreen screen(B_MAIN_SCREEN_ID);
68 	fWindow = new ScreenSaverWindow(screen.Frame());
69 	fPasswordWindow = new PasswordWindow();
70 	fRunner = new ScreenSaverRunner(fWindow, fWindow->ChildAt(0), false, fSettings);
71 
72 	fSaver = fRunner->ScreenSaver();
73 	if (fSaver) {
74 		fWindow->SetSaver(fSaver);
75 		fRunner->Run();
76 	} else {
77 		fprintf(stderr, "could not load the screensaver addon\n");
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 		if (fWindow->SetFullScreen(false) == B_OK) {
124 			fWindow->Sync();
125 				// TODO: is that needed?
126 			ShowCursor();
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, "turn off 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 			if (fWindow->Lock()) {
231 				if (fWindow->SetFullScreen(true) == B_OK) {
232 					HideCursor();
233 					fPasswordWindow->Hide();
234 				}
235 
236 				fRunner->Resume();
237 				fWindow->Unlock();
238 			}
239 
240 			_QueueTurnOffScreen();
241 			break;
242 
243 		case kMsgTurnOffScreen:
244 			_SetDPMSMode(B_DPMS_OFF);
245 			break;
246 		case kMsgSuspendScreen:
247 			_SetDPMSMode(B_DPMS_SUSPEND);
248 			break;
249 		case kMsgStandByScreen:
250 			_SetDPMSMode(B_DPMS_STAND_BY);
251 			break;
252 
253 		default:
254 			BApplication::MessageReceived(message);
255  			break;
256 	}
257 }
258 
259 
260 bool
261 ScreenBlanker::QuitRequested()
262 {
263 	if (fSettings.LockEnable()
264 		&& system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) {
265 		_ShowPasswordWindow();
266 		return false;
267 	}
268 
269 	_Shutdown();
270 	return true;
271 }
272 
273 
274 void
275 ScreenBlanker::_Shutdown()
276 {
277 	delete fRunner;
278 
279 	if (fWindow) {
280 		fWindow->Hide();
281 
282 		if (fWindow->Lock())
283 			fWindow->Quit();
284 	}
285 }
286 
287 
288 //	#pragma mark -
289 
290 
291 int
292 main(int, char**)
293 {
294 	ScreenBlanker app;
295 	app.Run();
296 	return 0;
297 }
298