xref: /haiku/src/bin/screen_blanker/ScreenBlanker.cpp (revision b46615c55ad2c8fe6de54412055a0713da3d610a)
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 		fWindow->ChildAt(0)->SetViewColor(0, 0, 0);
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 		fWindow->Sync();
124 			// TODO: is that needed?
125 		ShowCursor();
126 		if (fPasswordWindow->IsHidden())
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, "suspend 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 		{
231 			if (fWindow->Lock()) {
232 				HideCursor();
233 				fPasswordWindow->SetPassword("");
234 				fPasswordWindow->Hide();
235 
236 				fRunner->Resume();
237 				fWindow->Unlock();
238 			}
239 
240 			// Turn on the message filter again
241 			BMessage enable(kMsgEnableFilter);
242 			fWindow->PostMessage(&enable);
243 
244 			_QueueTurnOffScreen();
245 			break;
246 		}
247 
248 		case kMsgTurnOffScreen:
249 			_SetDPMSMode(B_DPMS_OFF);
250 			break;
251 		case kMsgSuspendScreen:
252 			_SetDPMSMode(B_DPMS_SUSPEND);
253 			break;
254 		case kMsgStandByScreen:
255 			_SetDPMSMode(B_DPMS_STAND_BY);
256 			break;
257 
258 		default:
259 			BApplication::MessageReceived(message);
260  			break;
261 	}
262 }
263 
264 
265 bool
266 ScreenBlanker::QuitRequested()
267 {
268 	if (fSettings.LockEnable()
269 		&& system_time() - fBlankTime > fSettings.PasswordTime() - fSettings.BlankTime()) {
270 		_ShowPasswordWindow();
271 		return false;
272 	}
273 
274 	_Shutdown();
275 	return true;
276 }
277 
278 
279 void
280 ScreenBlanker::_Shutdown()
281 {
282 	if (fWindow) {
283 		fWindow->Hide();
284 
285 		if (fWindow->Lock())
286 			fWindow->Quit();
287 	}
288 
289 	delete fRunner;
290 }
291 
292 
293 //	#pragma mark -
294 
295 
296 int
297 main(int, char**)
298 {
299 	ScreenBlanker app;
300 	app.Run();
301 	return 0;
302 }
303