1/*
2 * Copyright 2003-2014, 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 *		Ryan Leavengood, leavengood@gmail.com
9 *		Puck Meerburg, puck@puckipedia.nl
10 */
11
12
13#include "ScreenBlanker.h"
14#include "ScreenSaverWindow.h"
15
16#include <Application.h>
17#include <View.h>
18
19#include <WindowPrivate.h>
20
21#include <syslog.h>
22
23
24//	#pragma mark - ScreenSaverFilter
25
26
27/* This message filter is what will close the screensaver upon user activity. */
28filter_result
29ScreenSaverFilter::Filter(BMessage* message, BHandler** target)
30{
31	// This guard is used to avoid sending multiple B_QUIT_REQUESTED messages
32	if (fEnabled) {
33		switch (message->what) {
34			case B_MOUSE_MOVED:
35			{
36				// ignore the initial B_MOUSE_MOVED sent by the app_server
37				// in test mode, all mouse move events are ignored
38				bool transitOnly = false;
39				if (fTestMode
40					|| (message->FindBool("be:transit_only", &transitOnly)
41						== B_OK && transitOnly))
42					return B_DISPATCH_MESSAGE;
43
44				// Fall through
45			}
46			case B_KEY_DOWN:
47			{
48				// we ignore the Print-Screen key to make screen shots of
49				// screen savers possible
50				int32 key;
51				if (message->FindInt32("key", &key) == B_OK && key == 0xe)
52					return B_DISPATCH_MESSAGE;
53
54				// Fall through
55			}
56			case B_MODIFIERS_CHANGED:
57			case B_UNMAPPED_KEY_DOWN:
58			case B_MOUSE_DOWN:
59				fEnabled = false;
60				be_app->PostMessage(B_QUIT_REQUESTED);
61				break;
62		}
63	} else if (message->what == B_KEY_DOWN) {
64		ScreenBlanker* app = dynamic_cast<ScreenBlanker*>(be_app);
65		if (app != NULL && app->IsPasswordWindowShown()) {
66			// Handle the escape key when the password window is showing
67			const char* string = NULL;
68			if (message->FindString("bytes", &string) == B_OK
69					&& string[0] == B_ESCAPE) {
70				be_app->PostMessage(kMsgResumeSaver);
71			}
72		}
73	}
74
75	return B_DISPATCH_MESSAGE;
76}
77
78
79//	#pragma mark - ScreenSaverWindow
80
81
82/*!
83	This is the BDirectWindow subclass that rendering occurs in.
84	A view is added to it so that BView based screensavers will work.
85*/
86ScreenSaverWindow::ScreenSaverWindow(BRect frame, bool test)
87	:
88	BDirectWindow(frame, "ScreenSaver Window",
89		B_NO_BORDER_WINDOW_LOOK, kWindowScreenFeel,
90		B_NOT_RESIZABLE | B_NOT_MOVABLE | B_NOT_MINIMIZABLE
91		| B_NOT_ZOOMABLE | B_NOT_CLOSABLE, B_ALL_WORKSPACES),
92	fTopView(NULL),
93	fSaverRunner(NULL),
94	fFilter(NULL)
95{
96	frame.OffsetTo(0, 0);
97	fTopView = new BView(frame, "ScreenSaver View", B_FOLLOW_ALL,
98		B_WILL_DRAW);
99	fTopView->SetViewColor(B_TRANSPARENT_COLOR);
100
101	fFilter = new ScreenSaverFilter(test);
102	fTopView->AddFilter(fFilter);
103
104	AddChild(fTopView);
105
106	// Ensure that this view receives keyboard and mouse input
107	fTopView->MakeFocus(true);
108	fTopView->SetEventMask(B_KEYBOARD_EVENTS | B_POINTER_EVENTS,
109		B_NO_POINTER_HISTORY);
110}
111
112
113ScreenSaverWindow::~ScreenSaverWindow()
114{
115	Hide();
116}
117
118
119void
120ScreenSaverWindow::MessageReceived(BMessage* message)
121{
122	switch (message->what) {
123		case kMsgEnableFilter:
124			fFilter->SetEnabled(true);
125			break;
126
127		default:
128			BWindow::MessageReceived(message);
129	}
130}
131
132
133bool
134ScreenSaverWindow::QuitRequested()
135{
136	be_app->PostMessage(B_QUIT_REQUESTED);
137	return true;
138}
139
140
141void
142ScreenSaverWindow::DirectConnected(direct_buffer_info* info)
143{
144	BScreenSaver* saver = _ScreenSaver();
145	if (saver != NULL)
146		saver->DirectConnected(info);
147}
148
149
150void
151ScreenSaverWindow::SetSaverRunner(ScreenSaverRunner* runner)
152{
153	fSaverRunner = runner;
154}
155
156
157BScreenSaver*
158ScreenSaverWindow::_ScreenSaver()
159{
160	if (fSaverRunner != NULL)
161		return fSaverRunner->ScreenSaver();
162
163	return NULL;
164}
165