aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2013-02-14 18:58:14 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2013-02-14 18:58:28 (GMT)
commitec7fe513c8ca241836fab4632fc56faedd0f1863 (patch)
tree5730015ada46c7f64952fd57edefca50674979fc /src
parentac27c8cb4235b548ac1d1a5d5472d04a198bddf2 (diff)
downloadfluxbox-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.
Diffstat (limited to 'src')
-rw-r--r--src/ClockTool.cc89
-rw-r--r--src/ClockTool.hh18
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";
56const char SWITCHES_24_12H[] = "kHTlIr"; 56const char SWITCHES_24_12H[] = "kHTlIr";
57const char SWITCH_AM_PM[] = "pP"; 57const char SWITCH_AM_PM[] = "pP";
58 58
59/** 59uint64_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
64int 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
71uint64_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
196ClockTool::~ClockTool() { 176ClockTool::~ClockTool() {
@@ -226,29 +206,29 @@ void ClockTool::hide() {
226 206
227void ClockTool::setTimeFormat(const std::string &format) { 207void ClockTool::setTimeFormat(const std::string &format) {
228 *m_timeformat = format; 208 *m_timeformat = format;
229 themeReconfigured(); 209 updateTime();
230} 210}
231 211
232void ClockTool::themeReconfigured() { 212void 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
272void ClockTool::updateTime() { 252void 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
284restart_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
306void ClockTool::updateSizing() { 290void 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