From 716532dd47d718cb548da5f65b53a8b744ce235f Mon Sep 17 00:00:00 2001 From: Mathias Gumz Date: Sat, 26 Jan 2013 09:21:47 +0100 Subject: [PATCH] Calculates timeouts of ClockTool based upon System Clock Users expect time switches to happen upon system clock times. Calculating the timeout for the next refresh of the shown time via the monotonic clock is wrong: The monotonic clock yields values based upon some arbitrary point in time which might be off a little bit to the system clock, a 'full' minute of the monotonic clock might be in the midst of a system clock minute. --- src/ClockTool.cc | 9 +++++---- src/FbTk/FbTime.cc | 24 ++++++++++++++---------- src/FbTk/FbTime.hh | 15 ++++++++++----- src/FbTk/Timer.cc | 6 +++--- src/Window.cc | 8 ++++---- 5 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/ClockTool.cc b/src/ClockTool.cc index 3591f4fe..b4792fe0 100644 --- a/src/ClockTool.cc +++ b/src/ClockTool.cc @@ -70,12 +70,13 @@ int showSeconds(const std::string& fmt_string) { uint64_t calcNextTimeout(const std::string& fmt_string) { - if (showSeconds(fmt_string)) { // microseconds till next full second - return FbTk::FbTime::remainingNext(FbTk::FbTime::IN_SECONDS); + uint64_t now = FbTk::FbTime::system(); + uint64_t unit = FbTk::FbTime::IN_SECONDS; + if (!showSeconds(fmt_string)) { // microseconds till next full minute + unit *= 60L; } - // microseconds until next full minute - return FbTk::FbTime::remainingNext(60L * FbTk::FbTime::IN_SECONDS); + return FbTk::FbTime::remainingNext(now, unit); } diff --git a/src/FbTk/FbTime.cc b/src/FbTk/FbTime.cc index d0ef7318..c86edb10 100644 --- a/src/FbTk/FbTime.cc +++ b/src/FbTk/FbTime.cc @@ -21,6 +21,8 @@ #include "FbTime.hh" +#include +#include #ifdef HAVE_CLOCK_GETTIME // linux|*bsd|solaris @@ -28,16 +30,16 @@ namespace { -uint64_t _now() { +uint64_t _mono() { - uint64_t n = 0L; + uint64_t t = 0L; timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { - n = (ts.tv_sec * FbTk::FbTime::IN_SECONDS) + (ts.tv_nsec / 1000L); + t = (ts.tv_sec * FbTk::FbTime::IN_SECONDS) + (ts.tv_nsec / 1000L); } - return n; + return t; } } @@ -59,7 +61,7 @@ uint64_t _now() { namespace { -uint64_t _now() { +uint64_t _mono() { // mach_absolute_time() * info.numer / info.denom yields // nanoseconds. @@ -85,13 +87,15 @@ uint64_t _now() { - -uint64_t FbTk::FbTime::now() { - return ::_now(); +uint64_t FbTk::FbTime::mono() { + return ::_mono(); } -uint64_t FbTk::FbTime::remainingNext(uint64_t unit) { - return (unit - (::_now() % unit) - 1); +uint64_t FbTk::FbTime::system() { + static timeval v; + gettimeofday(&v, NULL); + return (v.tv_sec * FbTk::FbTime::IN_SECONDS) + v.tv_usec; } + diff --git a/src/FbTk/FbTime.hh b/src/FbTk/FbTime.hh index 2b33dd8c..3d80b122 100644 --- a/src/FbTk/FbTime.hh +++ b/src/FbTk/FbTime.hh @@ -34,7 +34,7 @@ namespace FbTk { -// time in micro-seconds, monotonic increasing +// time in micro-seconds // // interesting links: // @@ -44,12 +44,17 @@ namespace FbTk { namespace FbTime { const uint64_t IN_MILLISECONDS = 1000L; - const uint64_t IN_SECONDS = 1000L * 1000L; + const uint64_t IN_SECONDS = 1000L * IN_MILLISECONDS; + const uint64_t IN_MINUTES = 60 * IN_SECONDS; - uint64_t now(); + uint64_t mono(); // point in time, always monotonic + uint64_t system(); // system time, might jump (DST, leap seconds) - // calculates the remaining microseconds up to the next full 'unit' - uint64_t remainingNext(uint64_t unit); + // calculates the remaining microseconds from 'now' up to the + // next full 'unit' + inline uint64_t remainingNext(uint64_t now, uint64_t unit) { + return (unit - (now % unit) - 1); + } } // namespace FbTime diff --git a/src/FbTk/Timer.cc b/src/FbTk/Timer.cc index 2404773d..1bec8934 100644 --- a/src/FbTk/Timer.cc +++ b/src/FbTk/Timer.cc @@ -117,7 +117,7 @@ void Timer::start() { // it from s_timerlist before restarting it stop(); - m_start = FbTk::FbTime::now(); + m_start = FbTk::FbTime::mono(); // interval timers have their timeout change every // time they are started! @@ -158,7 +158,7 @@ void Timer::updateTimers(int fd) { FD_SET(fd, &rfds); bool overdue = false; - uint64_t now = FbTime::now(); + uint64_t now = FbTime::mono(); uint64_t end_time; // search for overdue timers @@ -192,7 +192,7 @@ void Timer::updateTimers(int fd) { static std::vector timeouts; - now = FbTime::now(); + now = FbTime::mono(); for (it = s_timerlist.begin(); it != s_timerlist.end(); ++it ) { if (now < (*it)->getEndTime()) { break; diff --git a/src/Window.cc b/src/Window.cc index a15c6e0d..1ee88536 100644 --- a/src/Window.cc +++ b/src/Window.cc @@ -550,7 +550,7 @@ void FluxboxWindow::init() { m_workspacesig.emit(*this); - m_creation_time = FbTk::FbTime::now(); + m_creation_time = FbTk::FbTime::mono(); frame().frameExtentSig().emit(); @@ -2206,7 +2206,7 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) { // just after creation if the user has a saved position/size if (m_creation_time) { - uint64_t now = FbTk::FbTime::now(); + uint64_t now = FbTk::FbTime::mono(); Remember& rinst = Remember::instance(); @@ -2310,12 +2310,12 @@ void FluxboxWindow::keyPressEvent(XKeyEvent &ke) { } // otherwise, make a note that the user is typing - m_last_keypress_time = FbTk::FbTime::now(); + m_last_keypress_time = FbTk::FbTime::mono(); } bool FluxboxWindow::isTyping() const { - uint64_t diff = FbTk::FbTime::now() - m_last_keypress_time; + uint64_t diff = FbTk::FbTime::mono() - m_last_keypress_time; return ((diff / 1000) < screen().noFocusWhileTypingDelay()); }