summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemko Tronçon <git@el-tramo.be>2009-11-24 18:09:37 (GMT)
committerRemko Tronçon <git@el-tramo.be>2009-11-24 18:09:37 (GMT)
commitc7fb528f0d80f9d96a2d84444352386d5d4288dc (patch)
treebc52f4729e948c5021ab322e6ad739f315d41140
parentea951bec1c4b84b739a9f435e0d17dbb99e4d724 (diff)
downloadswift-c7fb528f0d80f9d96a2d84444352386d5d4288dc.zip
swift-c7fb528f0d80f9d96a2d84444352386d5d4288dc.tar.bz2
Added SwifTools/Idle module.
-rw-r--r--SConstruct29
-rw-r--r--SwifTools/Idle/ActualIdleDetector.cpp29
-rw-r--r--SwifTools/Idle/ActualIdleDetector.h25
-rw-r--r--SwifTools/Idle/DummyIdleQuerier.h14
-rw-r--r--SwifTools/Idle/IdleDetector.cpp8
-rw-r--r--SwifTools/Idle/IdleDetector.h24
-rw-r--r--SwifTools/Idle/IdleQuerier.cpp8
-rw-r--r--SwifTools/Idle/IdleQuerier.h10
-rw-r--r--SwifTools/Idle/IdleQuerierTest/.gitignore1
-rw-r--r--SwifTools/Idle/IdleQuerierTest/IdleQuerierTest.cpp16
-rw-r--r--SwifTools/Idle/IdleQuerierTest/SConscript11
-rw-r--r--SwifTools/Idle/PlatformIdleQuerier.cpp26
-rw-r--r--SwifTools/Idle/PlatformIdleQuerier.h18
-rw-r--r--SwifTools/Idle/UnitTest/ActualIdleDetectorTest.cpp164
-rw-r--r--SwifTools/Idle/UnitTest/SConscript5
-rw-r--r--SwifTools/Idle/XSSIdleQuerier.cpp36
-rw-r--r--SwifTools/Idle/XSSIdleQuerier.h22
-rw-r--r--SwifTools/SConscript30
18 files changed, 464 insertions, 12 deletions
diff --git a/SConstruct b/SConstruct
index 0fa9a58..29be052 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,233 +1,248 @@
import sys, os
sys.path.append(Dir("BuildTools/SCons").abspath)
################################################################################
# Build variables
################################################################################
vars = Variables("config.py")
vars.Add('ccflags', "Extra C(++) compiler flags")
vars.Add('linkflags', "Extra linker flags")
vars.Add(EnumVariable("test", "Compile and run tests", "none", ["none", "all", "unit", "system"]))
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))
################################################################################
# Set up default build & configure environment
################################################################################
env = Environment(CPPPATH = "#", ENV = {'PATH' : os.environ['PATH']}, variables = vars)
Help(vars.GenerateHelpText(env))
env.Alias("dist", ["."])
# Default custom tools
env.Tool("Test", toolpath = ["#/BuildTools/SCons/Tools"])
env.Tool("WriteVal", toolpath = ["#/BuildTools/SCons/Tools"])
env.Tool("BuildVersion", toolpath = ["#/BuildTools/SCons/Tools"])
if env["PLATFORM"] == "darwin" :
env.Tool("Nib", toolpath = ["#/BuildTools/SCons/Tools"])
env.Tool("AppBundle", toolpath = ["#/BuildTools/SCons/Tools"])
if env["PLATFORM"] == "win32" :
env.Tool("WindowsBundle", toolpath = ["#/BuildTools/SCons/Tools"])
# Default compiler flags
env["CCFLAGS"] = env.get("ccflags", [])
env["LINKFLAGS"] = env.get("linkflags", [])
if env["optimize"] :
env.Append(CCFLAGS = "-O2")
if env["PLATFORM"] == "win32" :
env.Append(CCFLAGS = ["GL"])
env.Append(LINKFLAGS = ["/INCREMENTAL:NO", "/LTCG"])
if env["debug"] :
if env["PLATFORM"] == "win32" :
env.Append(CCFLAGS = ["/Zi", "/MDd"])
env.Append(LINKFLAGS = ["/DEBUG"])
else :
env.Append(CCFLAGS = "-g")
elif env["PLATFORM"] == "win32" :
env.Append(CCFLAGS = ["/MD"])
if env.get("universal", 0) :
assert(env["PLATFORM"] == "darwin")
env.Append(CCFLAGS = [
"-isysroot", "/Developer/SDKs/MacOSX10.4u.sdk",
"-arch", "i386",
"-arch", "ppc"])
env.Append(LINKFLAGS = [
"-mmacosx-version-min=10.4",
"-Wl", "-syslibroot,/Developer/SDKs/MacOSX10.4u.sdk",
"-arch", "i386",
"-arch", "ppc"])
if env["warnings"] :
if env["PLATFORM"] == "win32" :
env.Append(CCFLAGS = ["/Wall"])
else :
env.Append(CCFLAGS = ["-W", "-Wall"])
#env.Append(CCFLAGS = ["-W", "-Wall", "-Wredundant-decls", "-pedantic", "-Wno-long-long", "-Woverloaded-virtual", "-Wundef", "-Wfloat-equal", "-Wold-style-cast"])
if env.get("coverage", 0) :
assert(env["PLATFORM"] != "win32")
env.Append(CCFLAGS = ["-fprofile-arcs", "-ftest-coverage"])
env.Append(LINKFLAGS = ["-fprofile-arcs", "-ftest-coverage"])
if env["PLATFORM"] == "win32" :
env.Append(LIBS = ["dnsapi", "ws2_32", "wsock32"])
env.Append(CCFLAGS = ["/EHsc", "/nologo"])
env["LINKCOM"] = [env["LINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;1']
env["SHLINKCOM"] = [env["SHLINKCOM"], 'mt.exe -nologo -manifest ${TARGET}.manifest -outputresource:$TARGET;2']
if env["PLATFORM"] == "darwin" :
env.Append(FRAMEWORKS = "AppKit")
# Testing
env["TEST_TYPE"] = env["test"]
env.Alias("check", ".")
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", "") :
env["SWIFT_INSTALLDIR"] = Dir(ARGUMENTS["SWIFT_INSTALLDIR"]).abspath
conf_env = env.Clone()
Export("env")
Export("conf_env")
################################################################################
# Extend the default build environment (not affecting the configure env)
#
# Keeping both environments separated mostly because of SCons Issue 2391,
# although it doesn't hurt to separate them (e.g. not have pretty printed
# strings in config.log)
################################################################################
#if env["PLATFORM"] == "win32" :
# env["MSVC_BATCH"] = 1
# Pretty output
def colorize(command, target, color) :
colors = { "red": "31", "green": "32", "yellow": "33", "blue": "34" }
prefix = ""
suffix = ""
if sys.stdout.isatty() and env["PLATFORM"] != "win32":
prefix = "\033[0;" + colors[color] + ";140m"
suffix = "\033[0m"
return " " + prefix + command + suffix + " " + target
if int(ARGUMENTS.get("V", 0)) == 0:
env["CCCOMSTR"] = colorize("CC", "$TARGET", "green")
env["CXXCOMSTR"] = colorize("CXX", "$TARGET", "green")
env["LINKCOMSTR"] = colorize("LINK", "$TARGET", "red")
env["ARCOMSTR"] = colorize("AR", "$TARGET", "red")
env["RANLIBCOMSTR"] = colorize("RANLIB", "$TARGET", "red")
env["QT4_RCCCOMSTR"] = colorize("RCC", "$TARGET", "blue")
env["QT4_UICCOMSTR"] = colorize("UIC", "$TARGET", "blue")
env["QT4_MOCFROMHCOMSTR"] = colorize("MOC", "$TARGET", "blue")
env["QT4_MOCFROMCXXCOMSTR"] = colorize("MOC", "$TARGET", "blue")
env["GENCOMSTR"] = colorize("GEN", "$TARGET", "blue")
env["RCCOMSTR"] = colorize("RC", "$TARGET", "blue")
env["BUNDLECOMSTR"] = colorize("BUNDLE", "$TARGET", "blue")
env["NIBCOMSTR"] = colorize("NIB", "$TARGET", "blue")
env["NSISCOMSTR"] = colorize("NSIS", "$TARGET", "blue")
env["TESTCOMSTR"] = colorize("TEST", "$SOURCE", "yellow")
#Progress(colorize("DEP", "$TARGET", "red")
################################################################################
# Platform configuration
################################################################################
conf = Configure(conf_env)
if conf.CheckLib("z") :
env.Append(LIBS = "z")
env["ZLIB_FLAGS"] = ""
else :
SConscript("3rdParty/ZLib/SConscript")
if conf.CheckLib("dl") :
env.Append(LIBS = ["dl"])
if conf.CheckLib("c") :
env.Append(LIBS = ["c"])
if conf.CheckLib("resolv") :
env.Append(LIBS = ["resolv"])
# Expat
if conf.CheckCHeader("expat.h") and conf.CheckLib("expat") :
env["HAVE_EXPAT"] = 1
env["EXPAT_FLAGS"] = { "LIBS": ["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") :
env["HAVE_LIBXML"] = 1
env["LIBXML_FLAGS"] = { "LIBS": ["xml2"] }
conf.Finish()
if not env.get("HAVE_LIBXML", 0) :
libxml_env = conf_env.Clone()
libxml_env.Append(CPPPATH = ["/usr/include/libxml2"])
conf = Configure(libxml_env)
if conf.CheckCHeader("libxml/parser.h") and conf.CheckLib("xml2") :
env["HAVE_LIBXML"] = 1
env["LIBXML_FLAGS"] = { "CPPPATH": ["/usr/include/libxml2"], "LIBS": ["xml2"] }
conf.Finish()
# Bundled expat
bundledExpat = False
if not env.get("HAVE_EXPAT", 0) :
print "Expat or LibXML not found. Using bundled Expat"
SConscript("3rdParty/Expat/SConscript")
env["HAVE_EXPAT"] = 1
bundledExpat = True
# Qt
if env["qt"] :
env["QTDIR"] = env["qt"]
# OpenSSL
openssl_env = conf_env.Clone()
use_openssl = bool(env["openssl"])
openssl_prefix = env["openssl"] if isinstance(env["openssl"], str) else ""
openssl_flags = {}
if openssl_prefix :
openssl_flags = { "CPPPATH": [os.path.join(openssl_prefix, "include")] }
if env["PLATFORM"] == "win32" :
openssl_flags["LIBPATH"] = [os.path.join(openssl_prefix, "lib", "VC")]
env["OPENSSL_DIR"] = openssl_prefix
else :
openssl_flags["LIBPATH"] = [os.path.join(openssl_prefix, "lib")]
openssl_env.MergeFlags(openssl_flags)
openssl_conf = Configure(openssl_env)
if use_openssl and openssl_conf.CheckCHeader("openssl/ssl.h") :
env["HAVE_OPENSSL"] = 1
env["OPENSSL_FLAGS"] = openssl_flags
if env["PLATFORM"] == "win32" :
env["OPENSSL_FLAGS"]["LIBS"] = ["libeay32MT", "ssleay32MT"]
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
@@ -1,15 +1,35 @@
Import("env")
env["SWIFTOOLS_FLAGS"] = {
"LIBPATH": [Dir(".")],
"LIBS": ["SwifTools"]
}
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"
+ ])