diff options
author | Mathias Gumz <akira at fluxbox dot org> | 2013-02-14 18:58:14 (GMT) |
---|---|---|
committer | Mathias Gumz <akira at fluxbox dot org> | 2013-02-14 18:58:28 (GMT) |
commit | ec7fe513c8ca241836fab4632fc56faedd0f1863 (patch) | |
tree | 5730015ada46c7f64952fd57edefca50674979fc | |
parent | ac27c8cb4235b548ac1d1a5d5472d04a198bddf2 (diff) | |
download | fluxbox-ec7fe513c8ca241836fab4632fc56faedd0f1863.zip fluxbox-ec7fe513c8ca241836fab4632fc56faedd0f1863.tar.bz2 |
Trigger ClockTool every second, independent of the format string
It's hard to hit right moment to update the clock correctly: Either we are a
bit too early and the 'old time' is the same as the 'new time' and the clock
looks 'a bit off' or we are too late and the clock is 'a bit off'. This is
especially the case for format strings which do not show the second and thus
are updated only at the full minute (see bug #1082): if fluxbox does not
update the clock 'now' it would do it one minute later and thus the clock
might show the wrong time for roughly 1 minute.
Instead of coming up with something immensely clever we just trigger the
ClockTool every second. If no update of the shown time is needed fluxbox won't
do anything.
Some minor code reordering as byproduct.
-rw-r--r-- | src/ClockTool.cc | 89 | ||||
-rw-r--r-- | src/ClockTool.hh | 18 |
2 files changed, 44 insertions, 63 deletions
diff --git a/src/ClockTool.cc b/src/ClockTool.cc index b4792fe..b6d343f 100644 --- a/src/ClockTool.cc +++ b/src/ClockTool.cc | |||
@@ -56,26 +56,10 @@ const char SWITCHES_12_24H[] = "lIrkHT"; | |||
56 | const char SWITCHES_24_12H[] = "kHTlIr"; | 56 | const char SWITCHES_24_12H[] = "kHTlIr"; |
57 | const char SWITCH_AM_PM[] = "pP"; | 57 | const char SWITCH_AM_PM[] = "pP"; |
58 | 58 | ||
59 | /** | 59 | uint64_t calcNextTimeout() { |
60 | * return true if clock shows seconds. If clock doesn't show seconds then | ||
61 | * there is no need to wake up every second to redraw the clock. | ||
62 | */ | ||
63 | |||
64 | int showSeconds(const std::string& fmt_string) { | ||
65 | |||
66 | return FbTk::StringUtil::findCharFromAlphabetAfterTrigger( | ||
67 | fmt_string, '%', SWITCHES_SECONDS, sizeof(SWITCHES_SECONDS), 0) != std::string::npos; | ||
68 | } | ||
69 | |||
70 | |||
71 | uint64_t calcNextTimeout(const std::string& fmt_string) { | ||
72 | 60 | ||
73 | uint64_t now = FbTk::FbTime::system(); | 61 | uint64_t now = FbTk::FbTime::system(); |
74 | uint64_t unit = FbTk::FbTime::IN_SECONDS; | 62 | uint64_t unit = FbTk::FbTime::IN_SECONDS; |
75 | if (!showSeconds(fmt_string)) { // microseconds till next full minute | ||
76 | unit *= 60L; | ||
77 | } | ||
78 | |||
79 | return FbTk::FbTime::remainingNext(now, unit); | 63 | return FbTk::FbTime::remainingNext(now, unit); |
80 | } | 64 | } |
81 | 65 | ||
@@ -161,7 +145,7 @@ ClockTool::ClockTool(const FbTk::FbWindow &parent, | |||
161 | screen.name() + ".strftimeFormat", screen.altName() + ".StrftimeFormat"), | 145 | screen.name() + ".strftimeFormat", screen.altName() + ".StrftimeFormat"), |
162 | m_stringconvertor(FbTk::StringConvertor::ToFbString) { | 146 | m_stringconvertor(FbTk::StringConvertor::ToFbString) { |
163 | // attach signals | 147 | // attach signals |
164 | m_tracker.join(theme.reconfigSig(), FbTk::MemFun(*this, &ClockTool::themeReconfigured)); | 148 | m_tracker.join(theme.reconfigSig(), FbTk::MemFun(*this, &ClockTool::updateTime)); |
165 | 149 | ||
166 | std::string time_locale = setlocale(LC_TIME, NULL); | 150 | std::string time_locale = setlocale(LC_TIME, NULL); |
167 | size_t pos = time_locale.find('.'); | 151 | size_t pos = time_locale.find('.'); |
@@ -172,12 +156,9 @@ ClockTool::ClockTool(const FbTk::FbWindow &parent, | |||
172 | 156 | ||
173 | _FB_USES_NLS; | 157 | _FB_USES_NLS; |
174 | 158 | ||
175 | m_timer.setTimeout(calcNextTimeout(*m_timeformat)); | ||
176 | |||
177 | FbTk::RefCount<FbTk::Command<void> > update_graphic(new FbTk::SimpleCommand<ClockTool>(*this, | 159 | FbTk::RefCount<FbTk::Command<void> > update_graphic(new FbTk::SimpleCommand<ClockTool>(*this, |
178 | &ClockTool::updateTime)); | 160 | &ClockTool::updateTime)); |
179 | m_timer.setCommand(update_graphic); | 161 | m_timer.setCommand(update_graphic); |
180 | m_timer.start(); | ||
181 | 162 | ||
182 | m_button.setGC(m_theme->textGC()); | 163 | m_button.setGC(m_theme->textGC()); |
183 | 164 | ||
@@ -189,8 +170,7 @@ ClockTool::ClockTool(const FbTk::FbWindow &parent, | |||
189 | FbTk::RefCount<FbTk::Command<void> > editformat_cmd(new EditClockFormatCmd()); | 170 | FbTk::RefCount<FbTk::Command<void> > editformat_cmd(new EditClockFormatCmd()); |
190 | menu.insert(_FB_XTEXT(Toolbar, ClockEditFormat, "Edit Clock Format", "edit Clock Format") , editformat_cmd); | 171 | menu.insert(_FB_XTEXT(Toolbar, ClockEditFormat, "Edit Clock Format", "edit Clock Format") , editformat_cmd); |
191 | 172 | ||
192 | 173 | updateTime(); | |
193 | themeReconfigured(); | ||
194 | } | 174 | } |
195 | 175 | ||
196 | ClockTool::~ClockTool() { | 176 | ClockTool::~ClockTool() { |
@@ -226,29 +206,29 @@ void ClockTool::hide() { | |||
226 | 206 | ||
227 | void ClockTool::setTimeFormat(const std::string &format) { | 207 | void ClockTool::setTimeFormat(const std::string &format) { |
228 | *m_timeformat = format; | 208 | *m_timeformat = format; |
229 | themeReconfigured(); | 209 | updateTime(); |
230 | } | 210 | } |
231 | 211 | ||
232 | void ClockTool::themeReconfigured() { | 212 | void ClockTool::themeReconfigured() { |
233 | updateTime(); | ||
234 | 213 | ||
235 | // + 2 to make the entire text fit inside | 214 | // + 2 to make the entire text fit inside |
236 | // we only replace numbers with zeros because everything else should be | 215 | // we only replace numbers with zeros because everything else should be |
237 | // relatively static. If we replace all text with zeros then widths of | 216 | // relatively static. If we replace all text with zeros then widths of |
217 | |||
238 | // proportional fonts with some strftime formats will be considerably off. | 218 | // proportional fonts with some strftime formats will be considerably off. |
239 | FbTk::FbString text(m_button.text().logical()); | 219 | const FbTk::FbString& t = m_button.text().logical(); |
220 | size_t s = t.size() + 2; | ||
221 | FbTk::FbString text(s, '0'); | ||
240 | 222 | ||
241 | int textlen = text.size(); | 223 | for (size_t i = 0; i < (s - 2); ++i) { |
242 | for (int i=0; i < textlen; ++i) { | 224 | if (!isdigit(t[i])) |
243 | if (isdigit(text[i])) // don't bother replacing zeros | 225 | text[i] = t[i]; |
244 | text[i] = '0'; | ||
245 | } | 226 | } |
246 | text.append("00"); // pad | ||
247 | 227 | ||
248 | unsigned int new_width = m_button.width(); | 228 | unsigned int new_width = m_button.width(); |
249 | unsigned int new_height = m_button.height(); | 229 | unsigned int new_height = m_button.height(); |
250 | translateSize(orientation(), new_width, new_height); | 230 | translateSize(orientation(), new_width, new_height); |
251 | new_width = m_theme->font().textWidth(text.c_str(), text.size()); | 231 | new_width = m_theme->font().textWidth(text.c_str(), s); |
252 | translateSize(orientation(), new_width, new_height); | 232 | translateSize(orientation(), new_width, new_height); |
253 | if (new_width != m_button.width() || new_height != m_button.height()) { | 233 | if (new_width != m_button.width() || new_height != m_button.height()) { |
254 | resize(new_width, new_height); | 234 | resize(new_width, new_height); |
@@ -271,41 +251,44 @@ unsigned int ClockTool::height() const { | |||
271 | 251 | ||
272 | void ClockTool::updateTime() { | 252 | void ClockTool::updateTime() { |
273 | 253 | ||
274 | m_timer.setTimeout(calcNextTimeout(*m_timeformat)); | 254 | time_t t = time(NULL); |
275 | 255 | ||
276 | time_t the_time = time(NULL); | 256 | if (t != -1) { |
277 | if (the_time != -1) { | 257 | |
278 | char time_string[255]; | 258 | char buf[255]; |
279 | int time_string_len; | 259 | int len; |
280 | struct tm *time_type = localtime(&the_time); | 260 | struct tm* type; |
281 | if (time_type == 0) | 261 | FbTk::FbString text; |
282 | return; | 262 | |
263 | if ((type = localtime(&t)) == 0) | ||
264 | goto restart_timer; | ||
283 | 265 | ||
284 | #ifdef HAVE_STRFTIME | 266 | #ifdef HAVE_STRFTIME |
285 | time_string_len = strftime(time_string, 255, m_timeformat->c_str(), time_type); | ||
286 | if( time_string_len == 0) | ||
287 | return; | ||
288 | std::string text = m_stringconvertor.recode(time_string); | ||
289 | if (m_button.text().logical() == text) | ||
290 | return; | ||
291 | 267 | ||
292 | m_button.setText(text); | 268 | len = strftime(buf, sizeof(buf), m_timeformat->c_str(), type); |
269 | if (len == 0) | ||
270 | goto restart_timer; | ||
271 | |||
272 | text = m_stringconvertor.recode(buf); | ||
273 | if (m_button.text().logical() == text) | ||
274 | goto restart_timer; | ||
293 | 275 | ||
294 | unsigned int new_width = m_theme->font().textWidth(time_string, time_string_len) + 2; | ||
295 | if (new_width > m_button.width()) { | ||
296 | resize(new_width, m_button.height()); | ||
297 | resizeSig().emit(); | ||
298 | } | ||
299 | #else // dont have strftime so we have to set it to hour:minut | 276 | #else // dont have strftime so we have to set it to hour:minut |
300 | // sprintf(time_string, "%d:%d", ); | 277 | // sprintf(time_string, "%d:%d", ); |
301 | #endif // HAVE_STRFTIME | 278 | #endif // HAVE_STRFTIME |
279 | |||
280 | m_button.setText(text); | ||
281 | themeReconfigured(); | ||
302 | } | 282 | } |
283 | |||
284 | restart_timer: | ||
285 | m_timer.setTimeout(calcNextTimeout()); | ||
286 | m_timer.start(); | ||
303 | } | 287 | } |
304 | 288 | ||
305 | // Just change things that affect the size | 289 | // Just change things that affect the size |
306 | void ClockTool::updateSizing() { | 290 | void ClockTool::updateSizing() { |
307 | m_button.setBorderWidth(m_theme->border().width()); | 291 | m_button.setBorderWidth(m_theme->border().width()); |
308 | // resizes if new timeformat | ||
309 | themeReconfigured(); | 292 | themeReconfigured(); |
310 | } | 293 | } |
311 | 294 | ||
diff --git a/src/ClockTool.hh b/src/ClockTool.hh index 4f89b36..2872f33 100644 --- a/src/ClockTool.hh +++ b/src/ClockTool.hh | |||
@@ -72,18 +72,16 @@ private: | |||
72 | void reRender(); | 72 | void reRender(); |
73 | void updateSizing(); | 73 | void updateSizing(); |
74 | 74 | ||
75 | FbTk::TextButton m_button; | 75 | FbTk::TextButton m_button; |
76 | 76 | ||
77 | const FbTk::ThemeProxy<ToolTheme> &m_theme; | 77 | const FbTk::ThemeProxy<ToolTheme>& m_theme; |
78 | BScreen &m_screen; | 78 | BScreen& m_screen; |
79 | Pixmap m_pixmap; | 79 | Pixmap m_pixmap; |
80 | FbTk::Timer m_timer; | 80 | FbTk::Timer m_timer; |
81 | 81 | ||
82 | FbTk::Resource<std::string> m_timeformat; | 82 | FbTk::Resource<std::string> m_timeformat; |
83 | 83 | FbTk::StringConvertor m_stringconvertor; | |
84 | FbTk::StringConvertor m_stringconvertor; | 84 | FbTk::SignalTracker m_tracker; |
85 | |||
86 | FbTk::SignalTracker m_tracker; | ||
87 | }; | 85 | }; |
88 | 86 | ||
89 | #endif // CLOCKTOOL_HH | 87 | #endif // CLOCKTOOL_HH |