xref: /haiku/src/bin/screen_blanker/ScreenBlanker.cpp (revision 3cb015b1ee509d69c643506e8ff573808c86dcfc)
1 /*
2  * Copyright 2003-2006, 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_SUSPEND;
177 	if (fSettings.SuspendTime() == fSettings.StandByTime())
178 		flags &= ENABLE_DPMS_STAND_BY;
179 
180 	// start them off again
181 
182 	if (flags & ENABLE_DPMS_STAND_BY) {
183 		BMessage dpms(kMsgStandByScreen);
184 		fStandByScreenRunner = new BMessageRunner(BMessenger(this), &dpms,
185 			fSettings.StandByTime(), 1);
186 		if (fStandByScreenRunner->InitCheck() != B_OK)
187 			syslog(LOG_ERR, "standby screen saver runner failed\n");
188 	}
189 
190 	if (flags & ENABLE_DPMS_SUSPEND) {
191 		BMessage dpms(kMsgSuspendScreen);
192 		fSuspendScreenRunner = new BMessageRunner(BMessenger(this), &dpms,
193 			fSettings.SuspendTime(), 1);
194 		if (fSuspendScreenRunner->InitCheck() != B_OK)
195 			syslog(LOG_ERR, "turn off screen saver runner failed\n");
196 	}
197 
198 	if (flags & ENABLE_DPMS_OFF) {
199 		BMessage dpms(kMsgTurnOffScreen);
200 		fTurnOffScreenRunner = new BMessageRunner(BMessenger(this), &dpms,
201 			fSettings.OffTime(), 1);
202 		if (fTurnOffScreenRunner->InitCheck() != B_OK)
203 			syslog(LOG_ERR, "turn off screen saver runner failed\n");
204 	}
205 }
206 
207 
208 void
209 ScreenBlanker::MessageReceived(BMessage* message)
210 {
211 	switch (message->what) {
212 		case kMsgUnlock:
213 		{
214 			if (strcmp(fSettings.Password(), crypt(fPasswordWindow->Password(),
215 					fSettings.Password())) != 0) {
216 				beep();
217 				fPasswordWindow->SetPassword("");
218 				_QueueResumeScreenSaver();
219 			} else  {
220 				PRINT(("Quitting!\n"));
221 				_Shutdown();
222 				Quit();
223 			}
224 			break;
225 		}
226 
227 		case kMsgResumeSaver:
228 			if (fWindow->Lock()) {
229 				if (fWindow->SetFullScreen(true) == B_OK) {
230 					HideCursor();
231 					fPasswordWindow->Hide();
232 				}
233 
234 				fRunner->Resume();
235 				fWindow->Unlock();
236 			}
237 
238 			_QueueTurnOffScreen();
239 			break;
240 
241 		case kMsgTurnOffScreen:
242 			_SetDPMSMode(B_DPMS_OFF);
243 			break;
244 		case kMsgSuspendScreen:
245 			_SetDPMSMode(B_DPMS_SUSPEND);
246 			break;
247 		case kMsgStandByScreen:
248 			_SetDPMSMode(B_DPMS_STAND_BY);
249 			break;
250 
251 		default:
252 			BApplication::MessageReceived(message);
253  			break;
254 	}
255 }
256 
257 
258 bool
259 ScreenBlanker::QuitRequested()
260 {
261 	if (fSettings.LockEnable()
262 		&& system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) {
263 		_ShowPasswordWindow();
264 		return false;
265 	}
266 
267 	_Shutdown();
268 	return true;
269 }
270 
271 
272 void
273 ScreenBlanker::_Shutdown()
274 {
275 	delete fRunner;
276 
277 	if (fWindow) {
278 		fWindow->Hide();
279 
280 		if (fWindow->Lock())
281 			fWindow->Quit();
282 	}
283 }
284 
285 
286 //	#pragma mark -
287 
288 
289 int
290 main(int, char**)
291 {
292 	ScreenBlanker app;
293 	app.Run();
294 	return 0;
295 }
296