Fixed a bug in the screen saver code that could cause someone to get locked out

of their machine: if the password check is turned on, and the password window
is shown but times out (when the screen saver starts again after the standard
delay), the input filter never knew about this and would never try to end the
screen saver again.

The solution is to take the logic for turning off the screen saver out of the
input filter and put it in the screen blanker itself.

Also while working in the input filter I removed some debugging and a TODO that
I think cannot be fixed.

In the screen_blanker the exit after loading the settings file was removed
since the default settings now work for the screen_blanker.

Plus obviously code was added to handle exit upon user input as well as the
timing out of the password window.

If anyone has a better solution for the 250ms timeout to ignore initial mouse
moves, let me know.

Also I think the new calls should be nothrow, but I am not sure what the rule
is for that.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29488 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ryan Leavengood 2009-03-13 04:51:52 +00:00
parent f451e14bc2
commit cb6a084f20
5 changed files with 113 additions and 63 deletions

View File

@ -1,11 +1,12 @@
/*
* Copyright 2003-2008, Haiku.
* Copyright 2003-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Phipps
* Jérôme Duval, jerome.duval@free.fr
* Axel Dörfler, axeld@pinc-software.de
* Ryan Leavengood, leavengood@gmail.com
*/
@ -19,11 +20,8 @@
#include <Roster.h>
#include <Screen.h>
#include <Debug.h>
#include <new>
#define CALLED() SERIAL_PRINT(("%s\n", __PRETTY_FUNCTION__))
#include <syslog.h>
static const int32 kNeverBlankCornerSize = 10;
@ -38,8 +36,7 @@ static const int32 kMsgCornerInvoke = 'Scin';
extern "C" _EXPORT BInputServerFilter* instantiate_input_filter();
/** required C func to build the IS Filter */
/** Required C func to build the IS Filter */
BInputServerFilter*
instantiate_input_filter()
{
@ -54,16 +51,12 @@ ScreenSaverController::ScreenSaverController(ScreenSaverFilter *filter)
: BLooper("screensaver controller", B_LOW_PRIORITY),
fFilter(filter)
{
CALLED();
}
void
ScreenSaverController::MessageReceived(BMessage *message)
{
CALLED();
SERIAL_PRINT(("what %lx\n", message->what));
switch (message->what) {
case B_NODE_MONITOR:
fFilter->ReloadSettings();
@ -76,14 +69,9 @@ ScreenSaverController::MessageReceived(BMessage *message)
&& strcasecmp(signature, SCREEN_BLANKER_SIG) == 0) {
fFilter->SetEnabled(message->what == B_SOME_APP_LAUNCHED);
}
SERIAL_PRINT(("mime_sig %s\n", signature));
break;
}
case kMsgSuspendScreenSaver:
//fFilter->Suspend(msg);
break;
case kMsgCheckTime:
fFilter->CheckTime();
break;
@ -114,7 +102,6 @@ ScreenSaverFilter::ScreenSaverFilter()
fWatchingFile(false),
fEnabled(false)
{
CALLED();
fController = new (std::nothrow) ScreenSaverController(this);
if (fController == NULL)
return;
@ -185,40 +172,20 @@ ScreenSaverFilter::_WatchSettings()
void
ScreenSaverFilter::_Invoke()
{
CALLED();
if (fCurrentCorner == fNeverBlankCorner && fNeverBlankCorner != NO_CORNER
|| fSettings.TimeFlags() == SAVER_DISABLED
|| fEnabled
|| be_roster->IsRunning(SCREEN_BLANKER_SIG))
return;
SERIAL_PRINT(("we run screenblanker\n"));
if (be_roster->Launch(SCREEN_BLANKER_SIG) == B_OK)
fEnabled = true;
}
/*! Stops the running screen saver, if any */
void
ScreenSaverFilter::_Banish()
{
CALLED();
if (!fEnabled)
return;
SERIAL_PRINT(("we quit screenblanker\n"));
// Don't care if it fails
BMessenger blankerMessenger(SCREEN_BLANKER_SIG, -1, NULL);
blankerMessenger.SendMessage(B_QUIT_REQUESTED);
fEnabled = false;
}
void
ScreenSaverFilter::ReloadSettings()
{
CALLED();
BAutolock _(this);
bool isFirst = !fWatchingDirectory && !fWatchingFile;
@ -251,7 +218,7 @@ ScreenSaverFilter::ReloadSettings()
fRunner = new (std::nothrow) BMessageRunner(fController, &check,
fSnoozeTime);
if (fRunner == NULL || fRunner->InitCheck() != B_OK) {
SERIAL_PRINT(("screen saver filter runner init failed\n"));
syslog(LOG_ERR, "screen saver filter runner init failed\n");
}
}
@ -267,7 +234,6 @@ ScreenSaverFilter::SetEnabled(bool enabled)
void
ScreenSaverFilter::CheckTime()
{
CALLED();
BAutolock _(this);
bigtime_t now = system_time();
@ -307,9 +273,6 @@ ScreenSaverFilter::CheckCornerInvoke()
void
ScreenSaverFilter::_UpdateRectangles()
{
// TODO: make this better if possible at all (in a clean way)
CALLED();
fBlankRect = _ScreenCorner(fBlankCorner, kBlankCornerSize);
fNeverBlankRect = _ScreenCorner(fNeverBlankCorner, kNeverBlankCornerSize);
}
@ -382,20 +345,8 @@ ScreenSaverFilter::Filter(BMessage *message, BList *outList)
fCurrentCorner = NO_CORNER;
break;
}
case B_KEY_UP:
case B_KEY_DOWN:
{
// we ignore the Print-Screen key to make screen shots of
// screen savers possible
int32 key;
if (fEnabled && message->FindInt32("key", &key) == B_OK
&& key == 0xe)
return B_DISPATCH_MESSAGE;
}
}
_Banish();
return B_DISPATCH_MESSAGE;
}

View File

@ -19,8 +19,6 @@
#include <Node.h>
static const uint32 kMsgSuspendScreenSaver = 'susp';
class BMessageRunner;
class ScreenSaverFilter;
@ -59,7 +57,6 @@ private:
uint32 cornerSize);
void _Invoke();
void _Banish();
ScreenSaverSettings fSettings;
bigtime_t fLastEventTime;

View File

@ -1,11 +1,12 @@
/*
* Copyright 2003-2007, Haiku.
* Copyright 2003-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Phipps
* Jérôme Duval, jerome.duval@free.fr
* Axel Dörfler, axeld@pinc-software.de
* Ryan Leavengood, leavengood@gmail.com
*/
@ -58,8 +59,7 @@ void
ScreenBlanker::ReadyToRun()
{
if (!fSettings.Load()) {
fprintf(stderr, "could not load settings\n");
exit(1);
fprintf(stderr, "could not load settings, using defaults\n");
}
// create a BDirectWindow and start the render thread.
@ -123,7 +123,8 @@ ScreenBlanker::_ShowPasswordWindow()
fWindow->Sync();
// TODO: is that needed?
ShowCursor();
fPasswordWindow->Show();
if (fPasswordWindow->IsHidden())
fPasswordWindow->Show();
fWindow->Unlock();
}
@ -193,7 +194,7 @@ ScreenBlanker::_QueueTurnOffScreen()
fSuspendScreenRunner = new BMessageRunner(BMessenger(this), &dpms,
fSettings.SuspendTime(), 1);
if (fSuspendScreenRunner->InitCheck() != B_OK)
syslog(LOG_ERR, "turn off screen saver runner failed\n");
syslog(LOG_ERR, "suspend screen saver runner failed\n");
}
if (flags & ENABLE_DPMS_OFF) {
@ -226,6 +227,7 @@ ScreenBlanker::MessageReceived(BMessage* message)
}
case kMsgResumeSaver:
{
if (fWindow->Lock()) {
HideCursor();
fPasswordWindow->Hide();
@ -234,8 +236,13 @@ ScreenBlanker::MessageReceived(BMessage* message)
fWindow->Unlock();
}
// Turn on the message filter again
BMessage enable(kMsgEnableFilter);
BMessenger(fWindow).SendMessage(&enable);
_QueueTurnOffScreen();
break;
}
case kMsgTurnOffScreen:
_SetDPMSMode(B_DPMS_OFF);

View File

@ -1,10 +1,11 @@
/*
* Copyright 2003-2008, Haiku.
* Copyright 2003-2009, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Phipps
* Jérôme Duval, jerome.duval@free.fr
* Ryan Leavengood, leavengood@gmail.com
*/
@ -15,6 +16,44 @@
#include <WindowPrivate.h>
#include <syslog.h>
/* This message filter is what will close the screensaver upon user activity. */
filter_result
ScreenSaverFilter::Filter(BMessage* message, BHandler** target)
{
// This guard is used to avoid sending multiple B_QUIT_REQUESTED messages
if (fEnabled) {
switch (message->what) {
case B_KEY_DOWN:
{
// we ignore the Print-Screen key to make screen shots of
// screen savers possible
int32 key;
if (message->FindInt32("key", &key) == B_OK && key == 0xe)
return B_DISPATCH_MESSAGE;
// Fall through
}
case B_MOUSE_MOVED:
case B_MOUSE_DOWN:
fEnabled = false;
be_app->PostMessage(B_QUIT_REQUESTED);
break;
}
}
return B_DISPATCH_MESSAGE;
}
void
ScreenSaverFilter::SetEnabled(bool enabled)
{
fEnabled = enabled;
}
/*!
This is the BDirectWindow subclass that rendering occurs in.
@ -29,13 +68,31 @@ ScreenSaverWindow::ScreenSaverWindow(BRect frame)
frame.OffsetTo(0, 0);
fTopView = new BView(frame, "ScreenSaver View", B_FOLLOW_ALL, B_WILL_DRAW);
fTopView->SetViewColor(0, 0, 0);
fFilter = new ScreenSaverFilter();
fTopView->AddFilter(fFilter);
AddChild(fTopView);
// Ensure that this view receives keyboard input
fTopView->MakeFocus(true);
fTopView->SetEventMask(B_KEYBOARD_EVENTS, 0);
// A delay is necessary (250ms was chosen arbitrarily) before enabling the
// message filter because when the window first shows some mouse moved
// messages are sent to it automatically.
BMessage enable(kMsgEnableFilter);
fEnableRunner = new BMessageRunner(BMessenger(this), &enable, 250000LL, 1);
if (fEnableRunner->InitCheck() != B_OK)
syslog(LOG_ERR, "Runner to enable screen saver message filtering failed!\n");
}
ScreenSaverWindow::~ScreenSaverWindow()
{
Hide();
delete fEnableRunner;
delete fFilter;
}
@ -46,6 +103,21 @@ ScreenSaverWindow::SetSaver(BScreenSaver *saver)
}
void
ScreenSaverWindow::MessageReceived(BMessage *message)
{
switch (message->what) {
case kMsgEnableFilter:
fFilter->SetEnabled(true);
break;
default:
BWindow::MessageReceived(message);
break;
}
}
bool
ScreenSaverWindow::QuitRequested()
{

View File

@ -9,6 +9,26 @@
#include "ScreenSaver.h"
#include <DirectWindow.h>
#include <MessageFilter.h>
#include <MessageRunner.h>
const static uint32 kMsgEnableFilter = 'eflt';
class ScreenSaverFilter : public BMessageFilter {
public:
ScreenSaverFilter()
: BMessageFilter(B_ANY_DELIVERY, B_ANY_SOURCE),
fEnabled(false) {}
virtual filter_result Filter(BMessage* message, BHandler** target);
void SetEnabled(bool enabled);
private:
bool fEnabled;
};
class ScreenSaverWindow : public BDirectWindow {
@ -18,12 +38,15 @@ class ScreenSaverWindow : public BDirectWindow {
void SetSaver(BScreenSaver *saver);
virtual void MessageReceived(BMessage *message);
virtual bool QuitRequested();
virtual void DirectConnected(direct_buffer_info *info);
private:
BView *fTopView;
BScreenSaver *fSaver;
ScreenSaverFilter *fFilter;
BMessageRunner *fEnableRunner;
};
#endif // SCREEN_SAVER_WINDOW_H