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