From cb6a084f200d116677acdc7535f476626f09ccaa Mon Sep 17 00:00:00 2001 From: Ryan Leavengood Date: Fri, 13 Mar 2009 04:51:52 +0000 Subject: [PATCH] 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 --- .../screen_saver/ScreenSaverFilter.cpp | 59 ++------------- .../filters/screen_saver/ScreenSaverFilter.h | 3 - src/bin/screen_blanker/ScreenBlanker.cpp | 17 +++-- src/bin/screen_blanker/ScreenSaverWindow.cpp | 74 ++++++++++++++++++- src/bin/screen_blanker/ScreenSaverWindow.h | 23 ++++++ 5 files changed, 113 insertions(+), 63 deletions(-) diff --git a/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.cpp b/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.cpp index 946843a60e..0d144e95a5 100644 --- a/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.cpp +++ b/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.cpp @@ -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 #include -#include - #include - -#define CALLED() SERIAL_PRINT(("%s\n", __PRETTY_FUNCTION__)) +#include 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; } diff --git a/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.h b/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.h index 8d70a96054..b98b1aaf89 100644 --- a/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.h +++ b/src/add-ons/input_server/filters/screen_saver/ScreenSaverFilter.h @@ -19,8 +19,6 @@ #include -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; diff --git a/src/bin/screen_blanker/ScreenBlanker.cpp b/src/bin/screen_blanker/ScreenBlanker.cpp index ea3c45985a..59dafbc154 100644 --- a/src/bin/screen_blanker/ScreenBlanker.cpp +++ b/src/bin/screen_blanker/ScreenBlanker.cpp @@ -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); diff --git a/src/bin/screen_blanker/ScreenSaverWindow.cpp b/src/bin/screen_blanker/ScreenSaverWindow.cpp index cd6ba7d922..11cc301ef7 100644 --- a/src/bin/screen_blanker/ScreenSaverWindow.cpp +++ b/src/bin/screen_blanker/ScreenSaverWindow.cpp @@ -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 +#include + + +/* 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() { diff --git a/src/bin/screen_blanker/ScreenSaverWindow.h b/src/bin/screen_blanker/ScreenSaverWindow.h index bbedf54892..54bfd71ab0 100644 --- a/src/bin/screen_blanker/ScreenSaverWindow.h +++ b/src/bin/screen_blanker/ScreenSaverWindow.h @@ -9,6 +9,26 @@ #include "ScreenSaver.h" #include +#include +#include + + +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