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