From c7fb528f0d80f9d96a2d84444352386d5d4288dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be> Date: Tue, 24 Nov 2009 19:09:37 +0100 Subject: Added SwifTools/Idle module. diff --git a/SConstruct b/SConstruct index 0fa9a58..29be052 100644 --- a/SConstruct +++ b/SConstruct @@ -12,17 +12,17 @@ vars.Add(EnumVariable("test", "Compile and run tests", "none", ["none", "all", " vars.Add(BoolVariable("optimize", "Compile with optimizations turned on", "no")) vars.Add(BoolVariable("debug", "Compile with debug information", "yes" if os.name != "nt" else "no")) vars.Add(BoolVariable("warnings", "Compile with warnings turned on", - "yes" if os.name != "nt" else "no")) + "yes" if os.name != "nt" else "no")) if os.name != "nt" : - vars.Add(BoolVariable("coverage", "Compile with coverage information", "no")) + vars.Add(BoolVariable("coverage", "Compile with coverage information", "no")) if os.name == "posix" : - vars.Add(BoolVariable("valgrind", "Run tests with valgrind", "no")) + vars.Add(BoolVariable("valgrind", "Run tests with valgrind", "no")) if os.name == "mac" : - vars.Add(BoolVariable("universal", "Create universal binaries", "no")) + vars.Add(BoolVariable("universal", "Create universal binaries", "no")) if os.name == "nt" : - vars.Add(PathVariable("vcredist", "MSVC redistributable dir", "", PathVariable.PathAccept)) + vars.Add(PathVariable("vcredist", "MSVC redistributable dir", "", PathVariable.PathAccept)) if os.name == "nt" : - vars.Add(PackageVariable("bonjour", "Bonjour SDK location", "yes")) + vars.Add(PackageVariable("bonjour", "Bonjour SDK location", "yes")) vars.Add(PackageVariable("openssl", "OpenSSL location", "yes")) vars.Add(PathVariable("qt", "Qt location", "", PathVariable.PathAccept)) @@ -104,7 +104,7 @@ if "check" in ARGUMENTS or "check" in COMMAND_LINE_TARGETS : env["TEST_TYPE"] = "unit" env["TEST"] = (env["TEST_TYPE"] != "none") or env.GetOption("clean") if env.get("valgrind", 0) : - env["TEST_RUNNER"] = "valgrind --suppressions=QA/valgrind.supp -q --leak-check=full --track-origins=yes " + env["TEST_RUNNER"] = "valgrind --suppressions=QA/valgrind.supp -q --leak-check=full --track-origins=yes " # Packaging if ARGUMENTS.get("SWIFT_INSTALLDIR", "") : @@ -183,6 +183,21 @@ if conf.CheckCHeader("expat.h") and conf.CheckLib("expat") : conf.Finish() +# Xss +env["HAVE_XSS"] = 0 +if env["PLATFORM"] != "win32" and env["PLATFORM"] != "darwin" : + xss_flags = { + "LIBPATH": ["/usr/X11R6/lib"], + "LIBS": ["X11", "Xss"] + } + xss_env = conf_env.Clone() + xss_env.MergeFlags(xss_flags) + conf = Configure(xss_env) + if conf.CheckFunc("XScreenSaverQueryExtension") : + env["HAVE_XSS"] = 1 + env["XSS_FLAGS"] = xss_flags + conf.Finish() + # LibXML conf = Configure(conf_env) if conf.CheckCHeader("libxml/parser.h") and conf.CheckLib("xml2") : diff --git a/SwifTools/Idle/ActualIdleDetector.cpp b/SwifTools/Idle/ActualIdleDetector.cpp new file mode 100644 index 0000000..2e3f307 --- /dev/null +++ b/SwifTools/Idle/ActualIdleDetector.cpp @@ -0,0 +1,29 @@ +#include "SwifTools/Idle/ActualIdleDetector.h" + +#include <boost/bind.hpp> + +#include "SwifTools/Idle/IdleQuerier.h" +#include "Swiften/Network/Timer.h" +#include "Swiften/Network/TimerFactory.h" + +namespace Swift { + +ActualIdleDetector::ActualIdleDetector(IdleQuerier* querier, TimerFactory* timerFactory, int refreshRateSeconds) : querier(querier), isIdle(false) { + timer = timerFactory->createTimer(refreshRateSeconds*1000); + timer->onTick.connect(boost::bind(&ActualIdleDetector::handleTimerTick, this)); + timer->start(); +} + +ActualIdleDetector::~ActualIdleDetector() { + timer->stop(); +} + +void ActualIdleDetector::handleTimerTick() { + bool idle = (querier->getIdleTimeSeconds() >= getIdleTimeSeconds()); + if (idle != isIdle) { + isIdle = idle; + onIdleChanged(isIdle); + } +} + +} diff --git a/SwifTools/Idle/ActualIdleDetector.h b/SwifTools/Idle/ActualIdleDetector.h new file mode 100644 index 0000000..48428bb --- /dev/null +++ b/SwifTools/Idle/ActualIdleDetector.h @@ -0,0 +1,25 @@ +#pragma once + +#include <boost/shared_ptr.hpp> + +#include "SwifTools/Idle/IdleDetector.h" + +namespace Swift { + class IdleQuerier; + class TimerFactory; + class Timer; + + class ActualIdleDetector : public IdleDetector, public boost::bsignals::trackable { + public: + ActualIdleDetector(IdleQuerier*, TimerFactory*, int refreshRateSeconds); + ~ActualIdleDetector(); + + private: + void handleTimerTick(); + + private: + IdleQuerier* querier; + bool isIdle; + boost::shared_ptr<Timer> timer; + }; +} diff --git a/SwifTools/Idle/DummyIdleQuerier.h b/SwifTools/Idle/DummyIdleQuerier.h new file mode 100644 index 0000000..b8ba776 --- /dev/null +++ b/SwifTools/Idle/DummyIdleQuerier.h @@ -0,0 +1,14 @@ +#pragma once + +#include "SwifTools/Idle/IdleQuerier.h" + +namespace Swift { + class DummyIdleQuerier : public IdleQuerier { + public: + DummyIdleQuerier() {} + + virtual int getIdleTimeSeconds() { + return 0; + } + }; +} diff --git a/SwifTools/Idle/IdleDetector.cpp b/SwifTools/Idle/IdleDetector.cpp new file mode 100644 index 0000000..42559cd --- /dev/null +++ b/SwifTools/Idle/IdleDetector.cpp @@ -0,0 +1,8 @@ +#include "SwifTools/Idle/IdleDetector.h" + +namespace Swift { + +IdleDetector::~IdleDetector() { +} + +} diff --git a/SwifTools/Idle/IdleDetector.h b/SwifTools/Idle/IdleDetector.h new file mode 100644 index 0000000..1fb3d69 --- /dev/null +++ b/SwifTools/Idle/IdleDetector.h @@ -0,0 +1,24 @@ +#pragma once + +#include <boost/signals.hpp> +#include <boost/shared_ptr.hpp> + +namespace Swift { + class IdleDetector { + public: + virtual ~IdleDetector(); + + void setIdleTimeSeconds(int time) { + idleTimeSeconds = time; + } + + int getIdleTimeSeconds() const { + return idleTimeSeconds; + } + + boost::signal<void (bool /* isIdle */)> onIdleChanged; + + private: + int idleTimeSeconds; + }; +} diff --git a/SwifTools/Idle/IdleQuerier.cpp b/SwifTools/Idle/IdleQuerier.cpp new file mode 100644 index 0000000..0974aba --- /dev/null +++ b/SwifTools/Idle/IdleQuerier.cpp @@ -0,0 +1,8 @@ +#include "SwifTools/Idle/IdleQuerier.h" + +namespace Swift { + +IdleQuerier::~IdleQuerier() { +} + +} diff --git a/SwifTools/Idle/IdleQuerier.h b/SwifTools/Idle/IdleQuerier.h new file mode 100644 index 0000000..71f201e --- /dev/null +++ b/SwifTools/Idle/IdleQuerier.h @@ -0,0 +1,10 @@ +#pragma once + +namespace Swift { + class IdleQuerier { + public: + virtual ~IdleQuerier(); + + virtual int getIdleTimeSeconds() = 0; + }; +} diff --git a/SwifTools/Idle/IdleQuerierTest/.gitignore b/SwifTools/Idle/IdleQuerierTest/.gitignore new file mode 100644 index 0000000..6c63ee9 --- /dev/null +++ b/SwifTools/Idle/IdleQuerierTest/.gitignore @@ -0,0 +1 @@ +IdleQuerierTest diff --git a/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp b/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp new file mode 100644 index 0000000..94f7e2b --- /dev/null +++ b/SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp @@ -0,0 +1,16 @@ +#include <iostream> + +#include "SwifTools/Idle/PlatformIdleQuerier.h" +#include "Swiften/Base/sleep.h" + +using namespace Swift; + +int main() { + PlatformIdleQuerier querier; + while (true) { + std::cout << "Idle time: " << querier.getIdleTimeSeconds() << std::endl; + Swift::sleep(1000); + } + + return 0; +} diff --git a/SwifTools/Idle/IdleQuerierTest/SConscript b/SwifTools/Idle/IdleQuerierTest/SConscript new file mode 100644 index 0000000..d45aeea --- /dev/null +++ b/SwifTools/Idle/IdleQuerierTest/SConscript @@ -0,0 +1,11 @@ +Import("env") + +if env["TEST"] : + myenv = env.Clone() + myenv.MergeFlags(myenv["SWIFTOOLS_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["BOOST_FLAGS"]) + myenv.MergeFlags(myenv.get("XSS_FLAGS", {})) + myenv.Append(LIBPATH = ["/usr/X11R6/lib"]) + myenv.Append(LIBS = ["X11", "Xss"]) + tester = myenv.Program("IdleQuerierTest", ["IdleQuerierTest.cpp"]) diff --git a/SwifTools/Idle/PlatformIdleQuerier.cpp b/SwifTools/Idle/PlatformIdleQuerier.cpp new file mode 100644 index 0000000..76a3f7d --- /dev/null +++ b/SwifTools/Idle/PlatformIdleQuerier.cpp @@ -0,0 +1,26 @@ +#include "SwifTools/Idle/PlatformIdleQuerier.h" + +#if defined(HAVE_XSS) +#include "SwifTools/Idle/XSSIdleQuerier.h" +#else +#include "SwifTools/Idle/DummyIdleQuerier.h" +#endif + +#include <cassert> +#include <iostream> + +namespace Swift { + +PlatformIdleQuerier::PlatformIdleQuerier() : querier(NULL) { +#if defined(HAVE_XSS) + querier = new XSSIdleQuerier(); +#else + querier = new DummyIdleQuerier(); +#endif +} + +PlatformIdleQuerier::~PlatformIdleQuerier() { + delete querier; +} + +} diff --git a/SwifTools/Idle/PlatformIdleQuerier.h b/SwifTools/Idle/PlatformIdleQuerier.h new file mode 100644 index 0000000..e567b0e --- /dev/null +++ b/SwifTools/Idle/PlatformIdleQuerier.h @@ -0,0 +1,18 @@ +#pragma once + +#include "SwifTools/Idle/IdleQuerier.h" + +namespace Swift { + class PlatformIdleQuerier : public IdleQuerier { + public: + PlatformIdleQuerier(); + ~PlatformIdleQuerier(); + + virtual int getIdleTimeSeconds() { + return querier->getIdleTimeSeconds(); + } + + private: + IdleQuerier* querier; + }; +} diff --git a/SwifTools/Idle/UnitTest/ActualIdleDetectorTest.cpp b/SwifTools/Idle/UnitTest/ActualIdleDetectorTest.cpp new file mode 100644 index 0000000..99a7099 --- /dev/null +++ b/SwifTools/Idle/UnitTest/ActualIdleDetectorTest.cpp @@ -0,0 +1,164 @@ +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> +#include <boost/bind.hpp> + +#include "SwifTools/Idle/ActualIdleDetector.h" +#include "SwifTools/Idle/IdleQuerier.h" +#include "Swiften/Base/foreach.h" +#include "Swiften/Network/TimerFactory.h" +#include "Swiften/Network/Timer.h" + +using namespace Swift; + +class ActualIdleDetectorTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(ActualIdleDetectorTest); + CPPUNIT_TEST(testDestructor); + CPPUNIT_TEST(testHandleTick_Idle); + CPPUNIT_TEST(testHandleTick_Idle_AlreadyIdle); + CPPUNIT_TEST(testHandleTick_NotIdle); + CPPUNIT_TEST(testHandleTick_NotIdle_AlreadyNotIdle); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp() { + querier = new MockIdleQuerier(); + timerFactory = new MockTimerFactory(); + idleEvents.clear(); + } + + void tearDown() { + delete timerFactory; + delete querier; + } + + void testDestructor() { + ActualIdleDetector* testling = createDetector(); + testling->setIdleTimeSeconds(15); + delete testling; + + querier->idleTime = 15; + timerFactory->updateTime(15000); + + CPPUNIT_ASSERT_EQUAL(0U, idleEvents.size()); + } + + void testHandleTick_Idle() { + std::auto_ptr<ActualIdleDetector> testling(createDetector()); + testling->setIdleTimeSeconds(15); + querier->idleTime = 15; + + timerFactory->updateTime(15000); + + CPPUNIT_ASSERT_EQUAL(1U, idleEvents.size()); + CPPUNIT_ASSERT(idleEvents[0]); + } + + void testHandleTick_Idle_AlreadyIdle() { + std::auto_ptr<ActualIdleDetector> testling(createDetector()); + testling->setIdleTimeSeconds(15); + querier->idleTime = 15; + timerFactory->updateTime(15000); + + querier->idleTime = 30; + timerFactory->updateTime(30000); + + CPPUNIT_ASSERT_EQUAL(1U, idleEvents.size()); + CPPUNIT_ASSERT(idleEvents[0]); + } + + void testHandleTick_NotIdle() { + std::auto_ptr<ActualIdleDetector> testling(createDetector()); + testling->setIdleTimeSeconds(15); + querier->idleTime = 15; + timerFactory->updateTime(15000); + + querier->idleTime = 5; + timerFactory->updateTime(30000); + + CPPUNIT_ASSERT_EQUAL(2U, idleEvents.size()); + CPPUNIT_ASSERT(idleEvents[0]); + CPPUNIT_ASSERT(!idleEvents[1]); + } + + void testHandleTick_NotIdle_AlreadyNotIdle() { + std::auto_ptr<ActualIdleDetector> testling(createDetector()); + testling->setIdleTimeSeconds(15); + querier->idleTime = 5; + + timerFactory->updateTime(15000); + + CPPUNIT_ASSERT_EQUAL(0U, idleEvents.size()); + } + + private: + ActualIdleDetector* createDetector() { + ActualIdleDetector* detector = new ActualIdleDetector(querier, timerFactory, 10); + detector->onIdleChanged.connect(boost::bind(&ActualIdleDetectorTest::handleIdle, this, _1)); + return detector; + } + + void handleIdle(bool b) { + idleEvents.push_back(b); + } + + private: + struct MockIdleQuerier : public IdleQuerier { + MockIdleQuerier() : idleTime(0) {} + virtual int getIdleTimeSeconds() { return idleTime; } + int idleTime; + }; + + struct MockTimer : public Timer { + MockTimer(int interval) : interval(interval), running(false), lastTime(0) {} + + virtual void start() { + running = true; + } + + virtual void stop() { + running = false; + } + + virtual void updateTime(int currentTime) { + if (lastTime == currentTime) { + return; + } + if (running) { + int time = lastTime; + while (time <= currentTime) { + onTick(); + time += interval; + } + } + lastTime = currentTime; + } + + int interval; + bool running; + int lastTime; + }; + + struct MockTimerFactory : public TimerFactory { + MockTimerFactory() {} + + void updateTime(int milliseconds) { + foreach(boost::shared_ptr<MockTimer> timer, timers) { + timer->updateTime(milliseconds); + } + } + + boost::shared_ptr<Timer> createTimer(int milliseconds) { + boost::shared_ptr<MockTimer> timer(new MockTimer(milliseconds)); + timers.push_back(timer); + return timer; + } + + std::vector<boost::shared_ptr<MockTimer> > timers; + }; + + MockIdleQuerier* querier; + MockTimerFactory* timerFactory; + std::vector<bool> idleEvents; +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(ActualIdleDetectorTest); diff --git a/SwifTools/Idle/UnitTest/SConscript b/SwifTools/Idle/UnitTest/SConscript new file mode 100644 index 0000000..f193349 --- /dev/null +++ b/SwifTools/Idle/UnitTest/SConscript @@ -0,0 +1,5 @@ +Import("env") + +env.Append(UNITTEST_SOURCES = [ + File("ActualIdleDetectorTest.cpp") + ]) diff --git a/SwifTools/Idle/XSSIdleQuerier.cpp b/SwifTools/Idle/XSSIdleQuerier.cpp new file mode 100644 index 0000000..2259620 --- /dev/null +++ b/SwifTools/Idle/XSSIdleQuerier.cpp @@ -0,0 +1,36 @@ +#include "SwifTools/Idle/XSSIdleQuerier.h" + +#include <cassert> +#include <iostream> + +namespace Swift { + +XSSIdleQuerier::XSSIdleQuerier() : display(NULL), info(NULL) { + display = XOpenDisplay(NULL); + assert(display); + rootWindow = DefaultRootWindow(display); + int event, error; + available = XScreenSaverQueryExtension(display, &event, &error); + if (available) { + info = XScreenSaverAllocInfo(); + } + else { + std::cerr << "Warning: XScreenSaver extension not found. Idle time detection will not work." << std::endl; + } +} + +XSSIdleQuerier::~XSSIdleQuerier() { + XFree(info); +} + +int XSSIdleQuerier::getIdleTimeSeconds() { + if (available) { + XScreenSaverQueryInfo(display, rootWindow, info); + return info->idle / 1000; + } + else { + return 0; + } +} + +} diff --git a/SwifTools/Idle/XSSIdleQuerier.h b/SwifTools/Idle/XSSIdleQuerier.h new file mode 100644 index 0000000..476784d --- /dev/null +++ b/SwifTools/Idle/XSSIdleQuerier.h @@ -0,0 +1,22 @@ +#pragma once + +#include <X11/Xlib.h> +#include <X11/extensions/scrnsaver.h> + +#include "SwifTools/Idle/IdleQuerier.h" + +namespace Swift { + class XSSIdleQuerier : public IdleQuerier { + public: + XSSIdleQuerier(); + ~XSSIdleQuerier(); + + virtual int getIdleTimeSeconds(); + + private: + Display* display; + Window rootWindow; + bool available; + XScreenSaverInfo* info; + }; +} diff --git a/SwifTools/SConscript b/SwifTools/SConscript index 2caff5f..cff2c6b 100644 --- a/SwifTools/SConscript +++ b/SwifTools/SConscript @@ -6,10 +6,30 @@ env["SWIFTOOLS_FLAGS"] = { } myenv = env.Clone() - myenv.MergeFlags(myenv["BOOST_FLAGS"]) -myenv.StaticLibrary("SwifTools", [ - "Linkify.cpp" - ]) -SConscript(dirs = ["UnitTest"]) +sources = [ + "Idle/IdleDetector.cpp", + "Idle/ActualIdleDetector.cpp", + "Idle/IdleQuerier.cpp", + "Idle/PlatformIdleQuerier.cpp", + "Linkify.cpp", + ] + +if myenv["PLATFORM"] == "win32" : + pass +elif myenv["PLATFORM"] == "darwin" : + pass +elif myenv["HAVE_XSS"] : + myenv.Append(CPPDEFINES = ["HAVE_XSS"]) + sources += ["Idle/XSSIdleQuerier.cpp"] +else : + sources += ["Idle/DummyIdleQuerier.cpp"] + +myenv.StaticLibrary("SwifTools", sources) + +SConscript(dirs = [ + "Idle/IdleQuerierTest", + "Idle/UnitTest", + "UnitTest" + ]) -- cgit v0.10.2-6-g49f6