aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMathias Gumz <akira at fluxbox dot org>2012-08-28 08:51:55 (GMT)
committerMathias Gumz <akira at fluxbox dot org>2012-08-28 08:51:55 (GMT)
commit541c8c407b7ba8dd10f85bb48bcb5900270b3f84 (patch)
tree71a6abc0f2a43bcfd33f80b3b30b878f234cbf05 /src
parent60a53113e05db443af4d520883ec3145680642a8 (diff)
downloadfluxbox-541c8c407b7ba8dd10f85bb48bcb5900270b3f84.zip
fluxbox-541c8c407b7ba8dd10f85bb48bcb5900270b3f84.tar.bz2
changed timing functions to use a monotonic increasing clock
gettimeofday() is subject to be changed on daylight-saving or to ntp-related (think leap-seconds). even worse, it is subject to be changed BACK in time. this is hard to fix correctly (see commit 45726d3016e and bug #3560509). it is irrelevant for timers to know the nano-seconds since the epoch anyways.
Diffstat (limited to 'src')
-rw-r--r--src/AttentionNoticeHandler.cc2
-rw-r--r--src/ClockTool.cc37
-rw-r--r--src/FbTk/FbTime.cc97
-rw-r--r--src/FbTk/FbTime.hh58
-rw-r--r--src/FbTk/ImageControl.cc2
-rw-r--r--src/FbTk/Makefile.am1
-rw-r--r--src/FbTk/Menu.cc4
-rw-r--r--src/FbTk/Timer.cc232
-rw-r--r--src/FbTk/Timer.hh61
-rw-r--r--src/Slit.cc2
-rw-r--r--src/Toolbar.cc2
-rw-r--r--src/TooltipWindow.cc17
-rw-r--r--src/TooltipWindow.hh2
-rw-r--r--src/Window.cc34
-rw-r--r--src/Window.hh9
-rw-r--r--src/fluxbox.cc11
-rw-r--r--src/tests/testDemandAttention.cc5
-rw-r--r--src/tests/titletest.cc5
18 files changed, 315 insertions, 266 deletions
diff --git a/src/AttentionNoticeHandler.cc b/src/AttentionNoticeHandler.cc
index 0aaf266..1bb28b2 100644
--- a/src/AttentionNoticeHandler.cc
+++ b/src/AttentionNoticeHandler.cc
@@ -81,7 +81,7 @@ void AttentionNoticeHandler::addAttention(Focusable &client) {
81 RefCount<Command<void> > cmd(new ToggleFrameFocusCmd(client)); 81 RefCount<Command<void> > cmd(new ToggleFrameFocusCmd(client));
82 Timer *timer = new Timer(); 82 Timer *timer = new Timer();
83 timer->setCommand(cmd); 83 timer->setCommand(cmd);
84 timer->setTimeout(**timeout_res); 84 timer->setTimeout(**timeout_res * FbTk::FbTime::IN_MILLISECONDS);
85 timer->fireOnce(false); // will repeat until window has focus 85 timer->fireOnce(false); // will repeat until window has focus
86 timer->start(); 86 timer->start();
87 87
diff --git a/src/ClockTool.cc b/src/ClockTool.cc
index 95176a2..1fcdb53 100644
--- a/src/ClockTool.cc
+++ b/src/ClockTool.cc
@@ -35,6 +35,7 @@
35#include "FbTk/Menu.hh" 35#include "FbTk/Menu.hh"
36#include "FbTk/MenuItem.hh" 36#include "FbTk/MenuItem.hh"
37#include "FbTk/I18n.hh" 37#include "FbTk/I18n.hh"
38#include "FbTk/FbTime.hh"
38 39
39#ifdef HAVE_CONFIG_H 40#ifdef HAVE_CONFIG_H
40#include "config.h" 41#include "config.h"
@@ -45,16 +46,15 @@
45#else 46#else
46 #include <time.h> 47 #include <time.h>
47#endif 48#endif
48#include <sys/time.h>
49#include <typeinfo> 49#include <typeinfo>
50 50#include <cstdio>
51 51
52namespace { 52namespace {
53 53
54static const char SWITCHES_SECONDS[] = "crsSTX+"; 54const char SWITCHES_SECONDS[] = "crsSTX+";
55static const char SWITCHES_12_24H[] = "lIrkHT"; 55const char SWITCHES_12_24H[] = "lIrkHT";
56static const char SWITCHES_24_12H[] = "kHTlIr"; 56const char SWITCHES_24_12H[] = "kHTlIr";
57static const char SWITCH_AM_PM[] = "pP"; 57const char SWITCH_AM_PM[] = "pP";
58 58
59/** 59/**
60 * return true if clock shows seconds. If clock doesn't show seconds then 60 * return true if clock shows seconds. If clock doesn't show seconds then
@@ -68,23 +68,13 @@ int showSeconds(const std::string& fmt_string) {
68} 68}
69 69
70 70
71timeval calcNextTimeout(const std::string& fmt_string) { 71uint64_t calcNextTimeout(const std::string& fmt_string) {
72 timeval now;
73 timeval next;
74 gettimeofday(&now, 0);
75 next.tv_sec = 60 - (now.tv_sec % 60) - 1;
76 next.tv_usec = 1000000 - now.tv_usec;
77 if (next.tv_usec >= 1000000) {
78 next.tv_sec++;
79 next.tv_usec -= 1000000;
80 }
81 72
82 // wake up at next second-change 73 if (showSeconds(fmt_string)) { // microseconds till next full second
83 if (showSeconds(fmt_string)) { 74 return FbTk::FbTime::remainingNext(FbTk::FbTime::IN_SECONDS);
84 next.tv_sec = 0; 75 } else { // microseconds until next full minute
76 return FbTk::FbTime::remainingNext(60L * FbTk::FbTime::IN_SECONDS);
85 } 77 }
86
87 return next;
88} 78}
89 79
90 80
@@ -278,13 +268,10 @@ unsigned int ClockTool::height() const {
278} 268}
279 269
280void ClockTool::updateTime() { 270void ClockTool::updateTime() {
281 // update clock
282 timeval now;
283 gettimeofday(&now, 0);
284 time_t the_time = now.tv_sec;
285 271
286 m_timer.setTimeout(calcNextTimeout(*m_timeformat)); 272 m_timer.setTimeout(calcNextTimeout(*m_timeformat));
287 273
274 time_t the_time = time(NULL);
288 if (the_time != -1) { 275 if (the_time != -1) {
289 char time_string[255]; 276 char time_string[255];
290 int time_string_len; 277 int time_string_len;
diff --git a/src/FbTk/FbTime.cc b/src/FbTk/FbTime.cc
new file mode 100644
index 0000000..54eda75
--- /dev/null
+++ b/src/FbTk/FbTime.cc
@@ -0,0 +1,97 @@
1// FbTime.cc for FbTk - Fluxbox Toolkit
2// Copyright (c) 2012 Mathias Gumz (akira at fluxbox dot org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#include "FbTime.hh"
23
24
25
26#ifdef HAVE_CLOCK_GETTIME // linux|*bsd|solaris
27#include <time.h>
28
29namespace {
30
31uint64_t _now() {
32
33 uint64_t n = 0L;
34 timespec ts;
35
36 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
37 n = (ts.tv_sec * FbTk::FbTime::IN_SECONDS) + (ts.tv_nsec / 1000L);
38 }
39
40 return n;
41}
42
43}
44
45#endif // HAVE_CLOCK_GETTIME
46
47
48
49
50
51#ifdef HAVE_MACH_ABSOLUTE_TIME // macosx
52
53// http://stackoverflow.com/questions/5167269/clock-gettime-alternative-in-mac-os-x
54// https://github.com/ThomasHabets/monotonic_clock/blob/master/src/monotonic_mach.c
55// http://shiftedbits.org/2008/10/01/mach_absolute_time-on-the-iphone/
56
57
58#include <mach/mach_time.h>
59
60namespace {
61
62uint64_t _now() {
63
64 // mach_absolute_time() * info.numer / info.denom yields
65 // nanoseconds.
66
67 static double micro_scale = 0.001; // 1000ms == 1ns
68 static bool initial = true;
69
70 if (initial) {
71 initial = false;
72 mach_timebase_info_data_t info;
73 if (mach_timebase_info(&info) == 0) {
74 micro_scale *= static_cast<double>info.numer / static_cast<double>(info.denom);
75 }
76 }
77
78 return static_cast<uint64_t>(mach_absolute_time() * micro_scale);
79}
80
81}
82
83#endif // HAVE_MACH_ABSOLUTE_TIME
84
85
86
87
88
89uint64_t FbTk::FbTime::now() {
90 return ::_now();
91}
92
93
94uint64_t FbTk::FbTime::remainingNext(uint64_t unit) {
95 return (unit - (::_now() % unit) - 1);
96}
97
diff --git a/src/FbTk/FbTime.hh b/src/FbTk/FbTime.hh
new file mode 100644
index 0000000..2b33dd8
--- /dev/null
+++ b/src/FbTk/FbTime.hh
@@ -0,0 +1,58 @@
1// FbTime.hh for FbTk - Fluxbox Toolkit
2// Copyright (c) 2012 Mathias Gumz (akira at fluxbox dot org)
3//
4// Permission is hereby granted, free of charge, to any person obtaining a
5// copy of this software and associated documentation files (the "Software"),
6// to deal in the Software without restriction, including without limitation
7// the rights to use, copy, modify, merge, publish, distribute, sublicense,
8// and/or sell copies of the Software, and to permit persons to whom the
9// Software is furnished to do so, subject to the following conditions:
10//
11// The above copyright notice and this permission notice shall be included in
12// all copies or substantial portions of the Software.
13//
14// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20// DEALINGS IN THE SOFTWARE.
21
22#ifndef FBTK_FBTIME_HH
23#define FBTK_FBTIME_HH
24
25
26#ifdef HAVE_CONFIG_H
27#include "config.h"
28#endif // HAVE_CONFIG_H
29
30
31#ifdef HAVE_INTTYPES_H
32#include <inttypes.h>
33#endif // HAVE_INTTYPES_H
34
35namespace FbTk {
36
37// time in micro-seconds, monotonic increasing
38//
39// interesting links:
40//
41// http://www.python.org/dev/peps/pep-0418/#operating-system-time-functions
42// http://en.cppreference.com/w/cpp/chrono
43
44namespace FbTime {
45
46 const uint64_t IN_MILLISECONDS = 1000L;
47 const uint64_t IN_SECONDS = 1000L * 1000L;
48
49 uint64_t now();
50
51 // calculates the remaining microseconds up to the next full 'unit'
52 uint64_t remainingNext(uint64_t unit);
53
54} // namespace FbTime
55
56} // namespace FbTk
57
58#endif // FBTK_TIME_HH
diff --git a/src/FbTk/ImageControl.cc b/src/FbTk/ImageControl.cc
index fe6fde0..c99ef9a 100644
--- a/src/FbTk/ImageControl.cc
+++ b/src/FbTk/ImageControl.cc
@@ -188,7 +188,7 @@ ImageControl::ImageControl(int screen_num,
188 cache_max = cmax; 188 cache_max = cmax;
189 189
190 if (cache_timeout && s_timed_cache) { 190 if (cache_timeout && s_timed_cache) {
191 m_timer.setTimeout(cache_timeout); 191 m_timer.setTimeout(cache_timeout * FbTk::FbTime::IN_MILLISECONDS);
192 RefCount<Command<void> > clean_cache(new SimpleCommand<ImageControl>(*this, &ImageControl::cleanCache)); 192 RefCount<Command<void> > clean_cache(new SimpleCommand<ImageControl>(*this, &ImageControl::cleanCache));
193 m_timer.setCommand(clean_cache); 193 m_timer.setCommand(clean_cache);
194 m_timer.start(); 194 m_timer.start();
diff --git a/src/FbTk/Makefile.am b/src/FbTk/Makefile.am
index 171f27d..298b8c5 100644
--- a/src/FbTk/Makefile.am
+++ b/src/FbTk/Makefile.am
@@ -36,6 +36,7 @@ libFbTk_a_SOURCES = App.hh App.cc Color.cc Color.hh Command.hh \
36 Texture.cc Texture.hh TextureRender.hh TextureRender.cc \ 36 Texture.cc Texture.hh TextureRender.hh TextureRender.cc \
37 Shape.hh Shape.cc \ 37 Shape.hh Shape.cc \
38 Theme.hh Theme.cc ThemeItems.cc Timer.hh Timer.cc \ 38 Theme.hh Theme.cc ThemeItems.cc Timer.hh Timer.cc \
39 FbTime.cc FbTime.hh \
39 XFontImp.cc XFontImp.hh \ 40 XFontImp.cc XFontImp.hh \
40 Button.hh Button.cc \ 41 Button.hh Button.cc \
41 TextButton.hh TextButton.cc \ 42 TextButton.hh TextButton.cc \
diff --git a/src/FbTk/Menu.cc b/src/FbTk/Menu.cc
index a66b6c0..3632fc9 100644
--- a/src/FbTk/Menu.cc
+++ b/src/FbTk/Menu.cc
@@ -1006,7 +1006,7 @@ void Menu::motionNotifyEvent(XMotionEvent &me) {
1006 } 1006 }
1007 1007
1008 if (itmp->submenu()) { // start submenu open delay 1008 if (itmp->submenu()) { // start submenu open delay
1009 m_submenu_timer.setTimeout(theme()->getDelay()); 1009 m_submenu_timer.setTimeout(theme()->getDelay() * FbTk::FbTime::IN_MILLISECONDS);
1010 m_submenu_timer.start(); 1010 m_submenu_timer.start();
1011 } else if (isItemSelectable(w)){ 1011 } else if (isItemSelectable(w)){
1012 // else normal menu item 1012 // else normal menu item
@@ -1225,7 +1225,7 @@ void Menu::closeMenu() {
1225} 1225}
1226 1226
1227void Menu::startHide() { 1227void Menu::startHide() {
1228 m_hide_timer.setTimeout(theme()->getDelay()); 1228 m_hide_timer.setTimeout(theme()->getDelay() * FbTk::FbTime::IN_MILLISECONDS);
1229 m_hide_timer.start(); 1229 m_hide_timer.start();
1230} 1230}
1231 1231
diff --git a/src/FbTk/Timer.cc b/src/FbTk/Timer.cc
index 8b144db..6a478bd 100644
--- a/src/FbTk/Timer.cc
+++ b/src/FbTk/Timer.cc
@@ -1,5 +1,5 @@
1// Timer.cc for FbTk - Fluxbox Toolkit 1// Timer.cc for FbTk - Fluxbox Toolkit
2// Copyright (c) 2003 - 2006 Henrik Kinnunen (fluxgen at fluxbox dot org) 2// Copyright (c) 2003 - 2012 Henrik Kinnunen (fluxgen at fluxbox dot org)
3// 3//
4// Timer.cc for Blackbox - An X11 Window Manager 4// Timer.cc for Blackbox - An X11 Window Manager
5// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net) 5// Copyright (c) 1997 - 2000 Brad Hughes (bhughes at tcac.net)
@@ -32,10 +32,6 @@
32#define _GNU_SOURCE 32#define _GNU_SOURCE
33#endif // _GNU_SOURCE 33#endif // _GNU_SOURCE
34 34
35#ifdef HAVE_CONFIG_H
36#include "config.h"
37#endif // HAVE_CONFIG_H
38
39#ifdef HAVE_CASSERT 35#ifdef HAVE_CASSERT
40 #include <cassert> 36 #include <cassert>
41#else 37#else
@@ -55,9 +51,48 @@
55# include <winsock.h> 51# include <winsock.h>
56#endif 52#endif
57 53
58namespace FbTk { 54#include <cstdio>
55#include <set>
56
57
58namespace {
59
60struct TimerCompare {
61 bool operator() (const FbTk::Timer* a, const FbTk::Timer* b) {
62 return a->getEndTime() < b->getEndTime();
63 }
64};
65typedef std::set<FbTk::Timer*, TimerCompare> TimerList;
66
67TimerList s_timerlist;
68
69
70/// add a timer to the static list
71void addTimer(FbTk::Timer *timer) {
72
73 assert(timer);
74 int interval = timer->getInterval();
75
76 // interval timers have their timeout change every time they are started!
77 if (interval != 0) {
78 timer->setTimeout(interval * FbTk::FbTime::IN_SECONDS);
79 }
80
81 s_timerlist.insert(timer);
82}
59 83
60Timer::TimerList Timer::m_timerlist; 84/// remove a timer from the static list
85void removeTimer(FbTk::Timer *timer) {
86
87 assert(timer);
88 s_timerlist.erase(timer);
89}
90
91
92}
93
94
95namespace FbTk {
61 96
62Timer::Timer():m_timing(false), m_once(false), m_interval(0) { 97Timer::Timer():m_timing(false), m_once(false), m_interval(0) {
63 98
@@ -76,22 +111,8 @@ Timer::~Timer() {
76} 111}
77 112
78 113
79void Timer::setTimeout(time_t t) { 114void Timer::setTimeout(uint64_t timeout) {
80 m_timeout.tv_sec = t / 1000; 115 m_timeout = timeout;
81 m_timeout.tv_usec = t;
82 m_timeout.tv_usec -= (m_timeout.tv_sec * 1000);
83 m_timeout.tv_usec *= 1000;
84}
85
86
87void Timer::setTimeout(const timeval &t) {
88 m_timeout.tv_sec = t.tv_sec;
89 m_timeout.tv_usec = t.tv_usec;
90}
91
92void Timer::setTimeout(unsigned int secs, unsigned int usecs) {
93 m_timeout.tv_sec = secs;
94 m_timeout.tv_usec = usecs;
95} 116}
96 117
97void Timer::setCommand(const RefCount<Slot<void> > &cmd) { 118void Timer::setCommand(const RefCount<Slot<void> > &cmd) {
@@ -99,28 +120,24 @@ void Timer::setCommand(const RefCount<Slot<void> > &cmd) {
99} 120}
100 121
101void Timer::start() { 122void Timer::start() {
102 gettimeofday(&m_start, 0); 123
124 m_start = FbTk::FbTime::now();
103 125
104 // only add Timers that actually DO something 126 // only add Timers that actually DO something
105 if ((! m_timing || m_interval != 0) && m_handler) { 127 if ((! m_timing || m_interval != 0) && m_handler) {
106 m_timing = true; 128 m_timing = true;
107 addTimer(this); //add us to the list 129 ::addTimer(this);
108 } 130 }
109} 131}
110 132
111 133
112void Timer::stop() { 134void Timer::stop() {
113 m_timing = false; 135 m_timing = false;
114 removeTimer(this); //remove us from the list 136 ::removeTimer(this);
115} 137}
116 138
117void Timer::makeEndTime(timeval &tm) const { 139uint64_t Timer::getEndTime() const {
118 tm.tv_sec = m_start.tv_sec + m_timeout.tv_sec; 140 return m_start + m_timeout;
119 tm.tv_usec = m_start.tv_usec + m_timeout.tv_usec;
120 if (tm.tv_usec >= 1000000) {
121 tm.tv_usec -= 1000000;
122 tm.tv_sec++;
123 }
124} 141}
125 142
126 143
@@ -129,42 +146,34 @@ void Timer::fireTimeout() {
129 (*m_handler)(); 146 (*m_handler)();
130} 147}
131 148
149
132void Timer::updateTimers(int fd) { 150void Timer::updateTimers(int fd) {
151
133 fd_set rfds; 152 fd_set rfds;
134 timeval now, tm, *timeout = 0; 153 timeval tm;
154 timeval* timeout = 0;
155 TimerList::iterator it;
135 156
136 FD_ZERO(&rfds); 157 FD_ZERO(&rfds);
137 FD_SET(fd, &rfds); 158 FD_SET(fd, &rfds);
138 159
139 bool overdue = false; 160 bool overdue = false;
161 uint64_t now = FbTime::now();
162 uint64_t end_time;
140 163
141 // see, if the first timer in the 164 // see, if the first timer in the
142 // list is overdue 165 // list is overdue
143 if (!m_timerlist.empty()) { 166 if (!s_timerlist.empty()) {
144 gettimeofday(&now, 0);
145
146 Timer *timer = m_timerlist.front();
147
148 timer->makeEndTime(tm);
149 167
150 tm.tv_sec -= now.tv_sec; 168 Timer* timer = *s_timerlist.begin();
151 tm.tv_usec -= now.tv_usec; 169 end_time = timer->getEndTime();
152 170
153 while (tm.tv_usec < 0) { 171 if (end_time < now) {
154 if (tm.tv_sec > 0) {
155 tm.tv_sec--;
156 tm.tv_usec += 1000000;
157 } else {
158 overdue = true;
159 tm.tv_usec = 0;
160 break;
161 }
162 }
163
164 if (tm.tv_sec < 0) { // usec zero-ed above if negative
165 tm.tv_sec = 0;
166 tm.tv_usec = 0;
167 overdue = true; 172 overdue = true;
173 } else {
174 uint64_t diff = (end_time - now);
175 tm.tv_sec = diff / FbTime::IN_SECONDS;
176 tm.tv_usec = diff % FbTime::IN_SECONDS;
168 } 177 }
169 178
170 timeout = &tm; 179 timeout = &tm;
@@ -173,100 +182,41 @@ void Timer::updateTimers(int fd) {
173 // if not overdue, wait for the next xevent via the blocking 182 // if not overdue, wait for the next xevent via the blocking
174 // select(), so OS sends fluxbox to sleep. the select() will 183 // select(), so OS sends fluxbox to sleep. the select() will
175 // time out when the next timer has to be handled 184 // time out when the next timer has to be handled
176 if (!overdue && select(fd + 1, &rfds, 0, 0, timeout) != 0) 185 if (!overdue && select(fd + 1, &rfds, 0, 0, timeout) != 0) {
177 // didn't time out! x events are pending 186 // didn't time out! x events are pending
178 return; 187 return;
179
180 TimerList::iterator it;
181
182 // check for timer timeout
183 gettimeofday(&now, 0);
184
185 // someone set the date of the machine BACK
186 // so we have to adjust the start_time
187 static time_t last_time = 0;
188 if (now.tv_sec < last_time) {
189
190 time_t delta = last_time - now.tv_sec;
191
192 for (it = m_timerlist.begin(); it != m_timerlist.end(); ++it) {
193 (*it)->m_start.tv_sec -= delta;
194 }
195 } 188 }
196 last_time = now.tv_sec;
197
198 189
199 //must check end ...the timer might remove 190 now = FbTime::now();
200 //it self from the list (should be fixed in the future) 191 for (it = s_timerlist.begin(); it != s_timerlist.end(); ) {
201 for(it = m_timerlist.begin(); it != m_timerlist.end(); ) {
202 //This is to make sure we don't get an invalid iterator
203 //when we do fireTimeout
204 Timer &t = *(*it);
205 192
206 t.makeEndTime(tm); 193 // t->fireTimeout() might add timers to the list
207 194 // this invalidates 'it'. thus we store the current
208 if (((now.tv_sec < tm.tv_sec) || 195 // item here
209 (now.tv_sec == tm.tv_sec && now.tv_usec < tm.tv_usec))) 196 Timer* t = *it;
197 if (now < t->getEndTime()) {
210 break; 198 break;
211
212 t.fireTimeout();
213 // restart the current timer so that the start time is updated
214 if (! t.doOnce()) {
215 // must erase so that it's put into the right place in the list
216 it = m_timerlist.erase(it);
217 t.m_timing = false;
218 t.start();
219 } else {
220 // Since the default stop behaviour results in the timer
221 // being removed, we must remove it here, so that the iterator
222 // lives well. Another option would be to add it to another
223 // list, and then just go through that list and stop them all.
224 it = m_timerlist.erase(it);
225 t.stop();
226 } 199 }
227 }
228 200
229} 201 t->fireTimeout();
230 202
231void Timer::addTimer(Timer *timer) { 203 // find the iterator to the timer again
232 assert(timer); 204 // and continue working on the list
233 int interval = timer->getInterval(); 205 it = s_timerlist.find(t);
234 // interval timers have their timeout change every time they are started! 206 it++;
235 timeval tm; 207 s_timerlist.erase(t);
236 if (interval != 0) {
237 tm.tv_sec = timer->getStartTime().tv_sec;
238 tm.tv_usec = timer->getStartTime().tv_usec;
239
240 // now convert to interval
241 tm.tv_sec = interval - (tm.tv_sec % interval) - 1;
242 tm.tv_usec = 1000000 - tm.tv_usec;
243 if (tm.tv_usec == 1000000) {
244 tm.tv_usec = 0;
245 tm.tv_sec += 1;
246 }
247 timer->setTimeout(tm);
248 }
249
250 // set timeval to the time-of-trigger
251 timer->makeEndTime(tm);
252 208
253 // timer list is sorted by trigger time (i.e. start plus timeout) 209 if (! t->doOnce()) { // restart the current timer
254 TimerList::iterator it = m_timerlist.begin(); 210 t->m_timing = false;
255 TimerList::iterator it_end = m_timerlist.end(); 211 t->start();
256 for (; it != it_end; ++it) { 212 } else {
257 timeval trig; 213 t->stop();
258 (*it)->makeEndTime(trig);
259
260 if ((trig.tv_sec > tm.tv_sec) ||
261 (trig.tv_sec == tm.tv_sec &&
262 trig.tv_usec >= tm.tv_usec)) {
263 break;
264 } 214 }
265 } 215 }
266 m_timerlist.insert(it, timer);
267 216
268} 217}
269 218
219
270Command<void> *DelayedCmd::parse(const std::string &command, 220Command<void> *DelayedCmd::parse(const std::string &command,
271 const std::string &args, bool trusted) { 221 const std::string &args, bool trusted) {
272 222
@@ -280,7 +230,7 @@ Command<void> *DelayedCmd::parse(const std::string &command,
280 if (cmd == 0) 230 if (cmd == 0)
281 return 0; 231 return 0;
282 232
283 int delay = 200000; 233 int delay = 200;
284 StringUtil::fromString<int>(args.c_str() + err, delay); 234 StringUtil::fromString<int>(args.c_str() + err, delay);
285 235
286 return new DelayedCmd(cmd, delay); 236 return new DelayedCmd(cmd, delay);
@@ -294,10 +244,7 @@ DelayedCmd::DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout) {
294} 244}
295 245
296void DelayedCmd::initTimer(unsigned int timeout) { 246void DelayedCmd::initTimer(unsigned int timeout) {
297 timeval to; 247 m_timer.setTimeout(timeout * FbTime::IN_MILLISECONDS);
298 to.tv_sec = timeout/1000000;
299 to.tv_usec = timeout % 1000000;
300 m_timer.setTimeout(to);
301 m_timer.fireOnce(true); 248 m_timer.fireOnce(true);
302} 249}
303 250
@@ -307,9 +254,4 @@ void DelayedCmd::execute() {
307 m_timer.start(); 254 m_timer.start();
308} 255}
309 256
310void Timer::removeTimer(Timer *timer) {
311 assert(timer);
312 m_timerlist.remove(timer);
313}
314
315} // end namespace FbTk 257} // end namespace FbTk
diff --git a/src/FbTk/Timer.hh b/src/FbTk/Timer.hh
index 376eac0..241e327 100644
--- a/src/FbTk/Timer.hh
+++ b/src/FbTk/Timer.hh
@@ -27,26 +27,13 @@
27 27
28#include "RefCount.hh" 28#include "RefCount.hh"
29#include "Command.hh" 29#include "Command.hh"
30 30#include "FbTime.hh"
31#ifdef HAVE_CTIME
32 #include <ctime>
33#else
34 #include <time.h>
35#endif
36#include <list>
37#include <string>
38 31
39#ifdef HAVE_CONFIG_H 32#ifdef HAVE_CONFIG_H
40#include "config.h" 33#include "config.h"
41#endif //HAVE_CONFIG_H 34#endif //HAVE_CONFIG_H
42 35
43#ifdef HAVE_INTTYPES_H 36#include <string>
44#include <inttypes.h>
45#endif // HAVE_INTTYPES_H
46
47#include <sys/types.h>
48#include <sys/time.h>
49#include <unistd.h>
50 37
51namespace FbTk { 38namespace FbTk {
52 39
@@ -57,24 +44,21 @@ class Timer {
57public: 44public:
58 Timer(); 45 Timer();
59 explicit Timer(const RefCount<Slot<void> > &handler); 46 explicit Timer(const RefCount<Slot<void> > &handler);
60 virtual ~Timer(); 47 ~Timer();
61 48
62 void fireOnce(bool once) { m_once = once; } 49 void fireOnce(bool once) { m_once = once; }
63 /// set timeout 50 void setTimeout(uint64_t timeout);
64 void setTimeout(time_t val);
65 /// set timeout
66 void setTimeout(const timeval &val);
67 void setTimeout(unsigned int secs, unsigned int usecs);
68 void setCommand(const RefCount<Slot<void> > &cmd); 51 void setCommand(const RefCount<Slot<void> > &cmd);
52
69 template<typename Functor> 53 template<typename Functor>
70 void setFunctor(const Functor &functor) 54 void setFunctor(const Functor &functor) {
71 { setCommand(RefCount<Slot<void> >(new SlotImpl<Functor, void>(functor))); } 55 setCommand(RefCount<Slot<void> >(new SlotImpl<Functor, void>(functor)));
72 void setInterval(int val) { m_interval = val; } 56 }
73 /// start timing 57
58 void setInterval(int seconds) { m_interval = seconds; }
74 void start(); 59 void start();
75 /// stop timing
76 void stop(); 60 void stop();
77 /// update all timers 61
78 static void updateTimers(int file_descriptor); 62 static void updateTimers(int file_descriptor);
79 63
80 int isTiming() const { return m_timing; } 64 int isTiming() const { return m_timing; }
@@ -82,38 +66,29 @@ public:
82 66
83 int doOnce() const { return m_once; } 67 int doOnce() const { return m_once; }
84 68
85 const timeval &getTimeout() const { return m_timeout; } 69 uint64_t getTimeout() const { return m_timeout; }
86 const timeval &getStartTime() const { return m_start; } 70 uint64_t getStartTime() const { return m_start; }
87 void makeEndTime(timeval &tm) const; 71 uint64_t getEndTime() const;
88 72
89protected: 73protected:
90 /// force a timeout 74 /// force a timeout
91 void fireTimeout(); 75 void fireTimeout();
92 76
93private: 77private:
94 /// add a timer to the static list
95 static void addTimer(Timer *timer);
96 /// remove a timer from the static list
97 static void removeTimer(Timer *timer);
98
99 typedef std::list<Timer *> TimerList;
100 static TimerList m_timerlist; ///< list of all timers, sorted by next trigger time (start + timeout)
101
102 RefCount<Slot<void> > m_handler; ///< what to do on a timeout 78 RefCount<Slot<void> > m_handler; ///< what to do on a timeout
103 79
104 bool m_timing; ///< clock running? 80 bool m_timing; ///< clock running?
105 bool m_once; ///< do timeout only once? 81 bool m_once; ///< do timeout only once?
106 int m_interval; ///< Is an interval-only timer (e.g. clock) 82 int m_interval; ///< Is an interval-only timer (e.g. clock), in seconds
107 // note that intervals only take note of the seconds, not microseconds
108 83
109 timeval m_start; ///< start time 84 uint64_t m_start; ///< start time in microseconds
110 timeval m_timeout; ///< time length 85 uint64_t m_timeout; ///< time length in microseconds
111}; 86};
112 87
113/// executes a command after a specified timeout 88/// executes a command after a specified timeout
114class DelayedCmd: public Command<void> { 89class DelayedCmd: public Command<void> {
115public: 90public:
116 DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout = 200000); 91 DelayedCmd(const RefCount<Slot<void> > &cmd, unsigned int timeout = 200);
117 92
118 // this constructor has inverted order of parameters to avoid ambiguity with the previous 93 // this constructor has inverted order of parameters to avoid ambiguity with the previous
119 // constructor 94 // constructor
diff --git a/src/Slit.cc b/src/Slit.cc
index 02eb877..738a81a 100644
--- a/src/Slit.cc
+++ b/src/Slit.cc
@@ -279,7 +279,7 @@ Slit::Slit(BScreen &scr, FbTk::Layer &layer, const char *filename)
279 // move the frame out of sight for a moment 279 // move the frame out of sight for a moment
280 frame.window.move(-frame.window.width(), -frame.window.height()); 280 frame.window.move(-frame.window.width(), -frame.window.height());
281 // setup timer 281 // setup timer
282 m_timer.setTimeout(200); // default timeout 282 m_timer.setTimeout(200L * FbTk::FbTime::IN_MILLISECONDS); // default timeout
283 m_timer.fireOnce(true); 283 m_timer.fireOnce(true);
284 FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Slit>(*this, &Slit::toggleHidden)); 284 FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Slit>(*this, &Slit::toggleHidden));
285 m_timer.setCommand(toggle_hidden); 285 m_timer.setCommand(toggle_hidden);
diff --git a/src/Toolbar.cc b/src/Toolbar.cc
index a8b2c5b..1c22440 100644
--- a/src/Toolbar.cc
+++ b/src/Toolbar.cc
@@ -258,7 +258,7 @@ Toolbar::Toolbar(BScreen &scrn, FbTk::Layer &layer, size_t width):
258 frame.grab_x = frame.grab_y = 0; 258 frame.grab_x = frame.grab_y = 0;
259 259
260 // setup hide timer 260 // setup hide timer
261 m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay()); 261 m_hide_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
262 FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden)); 262 FbTk::RefCount<FbTk::Command<void> > toggle_hidden(new FbTk::SimpleCommand<Toolbar>(*this, &Toolbar::toggleHidden));
263 m_hide_timer.setCommand(toggle_hidden); 263 m_hide_timer.setCommand(toggle_hidden);
264 m_hide_timer.fireOnce(true); 264 m_hide_timer.fireOnce(true);
diff --git a/src/TooltipWindow.cc b/src/TooltipWindow.cc
index 0fb7273..77a6e1e 100644
--- a/src/TooltipWindow.cc
+++ b/src/TooltipWindow.cc
@@ -55,8 +55,11 @@ void TooltipWindow::raiseTooltip() {
55 55
56 resize(m_lastText); 56 resize(m_lastText);
57 reconfigTheme(); 57 reconfigTheme();
58 int h = theme()->iconbarTheme().text().font().height() + theme()->bevelWidth() * 2; 58
59 int w = theme()->iconbarTheme().text().font().textWidth(m_lastText) + theme()->bevelWidth() * 2; 59 FbTk::Font& font = theme()->iconbarTheme().text().font();
60
61 int h = font.height() + theme()->bevelWidth() * 2;
62 int w = font.textWidth(m_lastText) + theme()->bevelWidth() * 2;
60 63
61 Window root_ret; // not used 64 Window root_ret; // not used
62 Window window_ret; // not used 65 Window window_ret; // not used
@@ -91,11 +94,11 @@ void TooltipWindow::raiseTooltip() {
91 show(); 94 show();
92 clear(); 95 clear();
93 // TODO: make this use a TextButton like TextDialog does 96 // TODO: make this use a TextButton like TextDialog does
94 theme()->iconbarTheme().text().font().drawText(*this, screen().screenNumber(), 97 font.drawText(*this, screen().screenNumber(),
95 theme()->iconbarTheme().text().textGC(), 98 theme()->iconbarTheme().text().textGC(),
96 m_lastText, 99 m_lastText,
97 theme()->bevelWidth(), 100 theme()->bevelWidth(),
98 theme()->bevelWidth() + theme()->iconbarTheme().text().font().ascent()); 101 theme()->bevelWidth() + font.ascent());
99} 102}
100 103
101void TooltipWindow::updateText(const FbTk::BiDiString& text) { 104void TooltipWindow::updateText(const FbTk::BiDiString& text) {
diff --git a/src/TooltipWindow.hh b/src/TooltipWindow.hh
index 4d028b5..67bec90 100644
--- a/src/TooltipWindow.hh
+++ b/src/TooltipWindow.hh
@@ -47,7 +47,7 @@ public:
47 /// Sets the delay before the window pops up 47 /// Sets the delay before the window pops up
48 void setDelay(int delay) { 48 void setDelay(int delay) {
49 m_delay = delay; 49 m_delay = delay;
50 m_timer.setTimeout(delay); 50 m_timer.setTimeout(delay * FbTk::FbTime::IN_MILLISECONDS);
51 } 51 }
52 52
53 void hide(); 53 void hide();
diff --git a/src/Window.cc b/src/Window.cc
index 597bc08..33a4c9e 100644
--- a/src/Window.cc
+++ b/src/Window.cc
@@ -416,7 +416,7 @@ void FluxboxWindow::init() {
416 416
417 updateMWMHintsFromClient(*m_client); 417 updateMWMHintsFromClient(*m_client);
418 418
419 m_timer.setTimeout(fluxbox.getAutoRaiseDelay()); 419 m_timer.setTimeout(fluxbox.getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
420 FbTk::RefCount<FbTk::Command<void> > raise_cmd(new FbTk::SimpleCommand<FluxboxWindow>(*this, 420 FbTk::RefCount<FbTk::Command<void> > raise_cmd(new FbTk::SimpleCommand<FluxboxWindow>(*this,
421 &FluxboxWindow::raise)); 421 &FluxboxWindow::raise));
422 m_timer.setCommand(raise_cmd); 422 m_timer.setCommand(raise_cmd);
@@ -538,9 +538,7 @@ void FluxboxWindow::init() {
538 538
539 m_workspacesig.emit(*this); 539 m_workspacesig.emit(*this);
540 540
541 struct timeval now; 541 m_creation_time = FbTk::FbTime::now();
542 gettimeofday(&now, NULL);
543 m_creation_time = now.tv_sec;
544 542
545 frame().frameExtentSig().emit(); 543 frame().frameExtentSig().emit();
546 544
@@ -1049,15 +1047,10 @@ void FluxboxWindow::grabButtons() {
1049void FluxboxWindow::reconfigure() { 1047void FluxboxWindow::reconfigure() {
1050 1048
1051 applyDecorations(); 1049 applyDecorations();
1052
1053 setFocusFlag(m_focused); 1050 setFocusFlag(m_focused);
1054
1055 moveResize(frame().x(), frame().y(), frame().width(), frame().height()); 1051 moveResize(frame().x(), frame().y(), frame().width(), frame().height());
1056 1052 m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay() * FbTk::FbTime::IN_MILLISECONDS);
1057 m_timer.setTimeout(Fluxbox::instance()->getAutoRaiseDelay());
1058
1059 updateButtons(); 1053 updateButtons();
1060
1061 frame().reconfigure(); 1054 frame().reconfigure();
1062 menu().reconfigure(); 1055 menu().reconfigure();
1063 1056
@@ -2200,14 +2193,14 @@ void FluxboxWindow::configureRequestEvent(XConfigureRequestEvent &cr) {
2200 // don't let misbehaving clients (e.g. MPlayer) move/resize their windows 2193 // don't let misbehaving clients (e.g. MPlayer) move/resize their windows
2201 // just after creation if the user has a saved position/size 2194 // just after creation if the user has a saved position/size
2202 if (m_creation_time) { 2195 if (m_creation_time) {
2203 struct timeval now; 2196
2204 gettimeofday(&now, NULL); 2197 uint64_t now = FbTk::FbTime::now();
2205 2198
2206 Remember& rinst = Remember::instance(); 2199 Remember& rinst = Remember::instance();
2207 2200
2208 if (now.tv_sec > m_creation_time + 1) 2201 if (now > (m_creation_time + FbTk::FbTime::IN_SECONDS)) {
2209 m_creation_time = 0; 2202 m_creation_time = 0;
2210 else if (rinst.isRemembered(*client, Remember::REM_MAXIMIZEDSTATE) || 2203 } else if (rinst.isRemembered(*client, Remember::REM_MAXIMIZEDSTATE) ||
2211 rinst.isRemembered(*client, Remember::REM_FULLSCREENSTATE)) { 2204 rinst.isRemembered(*client, Remember::REM_FULLSCREENSTATE)) {
2212 cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight); 2205 cr.value_mask = cr.value_mask & ~(CWWidth | CWHeight);
2213 cr.value_mask = cr.value_mask & ~(CWX | CWY); 2206 cr.value_mask = cr.value_mask & ~(CWX | CWY);
@@ -2300,23 +2293,18 @@ void FluxboxWindow::keyPressEvent(XKeyEvent &ke) {
2300 // e.g., typed the command in a terminal 2293 // e.g., typed the command in a terminal
2301 if (ks == XK_KP_Enter || ks == XK_Return) { 2294 if (ks == XK_KP_Enter || ks == XK_Return) {
2302 // we'll actually reset the time for this one 2295 // we'll actually reset the time for this one
2303 m_last_keypress_time.tv_sec = 0; 2296 m_last_keypress_time = 0;
2304 return; 2297 return;
2305 } 2298 }
2306 2299
2307 // otherwise, make a note that the user is typing 2300 // otherwise, make a note that the user is typing
2308 gettimeofday(&m_last_keypress_time, 0); 2301 m_last_keypress_time = FbTk::FbTime::now();
2309} 2302}
2310 2303
2311bool FluxboxWindow::isTyping() const { 2304bool FluxboxWindow::isTyping() const {
2312 timeval now;
2313 if (gettimeofday(&now, NULL) == -1)
2314 return false;
2315
2316 unsigned int diff = 1000*(now.tv_sec - m_last_keypress_time.tv_sec);
2317 diff += (now.tv_usec - m_last_keypress_time.tv_usec)/1000;
2318 2305
2319 return (diff < screen().noFocusWhileTypingDelay()); 2306 uint64_t diff = FbTk::FbTime::now() - m_last_keypress_time;
2307 return ((diff / 1000) < screen().noFocusWhileTypingDelay());
2320} 2308}
2321 2309
2322void FluxboxWindow::buttonPressEvent(XButtonEvent &be) { 2310void FluxboxWindow::buttonPressEvent(XButtonEvent &be) {
diff --git a/src/Window.hh b/src/Window.hh
index 8c97c7b..09374af 100644
--- a/src/Window.hh
+++ b/src/Window.hh
@@ -33,11 +33,11 @@
33 33
34#include "FbTk/DefaultValue.hh" 34#include "FbTk/DefaultValue.hh"
35#include "FbTk/Timer.hh" 35#include "FbTk/Timer.hh"
36#include "FbTk/FbTime.hh"
36#include "FbTk/EventHandler.hh" 37#include "FbTk/EventHandler.hh"
37#include "FbTk/LayerItem.hh" 38#include "FbTk/LayerItem.hh"
38#include "FbTk/Signal.hh" 39#include "FbTk/Signal.hh"
39 40
40#include <sys/time.h>
41#include <vector> 41#include <vector>
42#include <string> 42#include <string>
43#include <memory> 43#include <memory>
@@ -529,14 +529,15 @@ private:
529 // state and hint signals 529 // state and hint signals
530 FbTk::Signal<FluxboxWindow &> m_workspacesig, m_statesig, m_layersig, m_hintsig; 530 FbTk::Signal<FluxboxWindow &> m_workspacesig, m_statesig, m_layersig, m_hintsig;
531 531
532 time_t m_creation_time; 532 uint64_t m_creation_time;
533 uint64_t m_last_keypress_time;
534 FbTk::Timer m_timer;
533 535
534 // Window states 536 // Window states
535 bool moving, resizing, m_initialized; 537 bool moving, resizing, m_initialized;
536 538
537 WinClient *m_attaching_tab; 539 WinClient *m_attaching_tab;
538 540
539 FbTk::Timer m_timer;
540 Display *display; /// display connection 541 Display *display; /// display connection
541 542
542 int m_button_grab_x, m_button_grab_y; // handles last button press event for move 543 int m_button_grab_x, m_button_grab_y; // handles last button press event for move
@@ -545,8 +546,6 @@ private:
545 int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window" 546 int m_last_resize_h, m_last_resize_w; // handles height/width for resize "window"
546 int m_last_pressed_button; 547 int m_last_pressed_button;
547 548
548 timeval m_last_keypress_time;
549
550 unsigned int m_workspace_number; 549 unsigned int m_workspace_number;
551 unsigned long m_current_state; // NormalState | IconicState | Withdrawn 550 unsigned long m_current_state; // NormalState | IconicState | Withdrawn
552 551
diff --git a/src/fluxbox.cc b/src/fluxbox.cc
index 77b9881..129ac80 100644
--- a/src/fluxbox.cc
+++ b/src/fluxbox.cc
@@ -306,7 +306,7 @@ Fluxbox::Fluxbox(int argc, char **argv,
306 // because it could affect ongoing menu stuff so we need to reconfig in 306 // because it could affect ongoing menu stuff so we need to reconfig in
307 // the next event "round". 307 // the next event "round".
308 FbTk::RefCount<FbTk::Command<void> > reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure)); 308 FbTk::RefCount<FbTk::Command<void> > reconfig_cmd(new FbTk::SimpleCommand<Fluxbox>(*this, &Fluxbox::timed_reconfigure));
309 m_reconfig_timer.setTimeout(0, 1); 309 m_reconfig_timer.setTimeout(1);
310 m_reconfig_timer.setCommand(reconfig_cmd); 310 m_reconfig_timer.setCommand(reconfig_cmd);
311 m_reconfig_timer.fireOnce(true); 311 m_reconfig_timer.fireOnce(true);
312 312
@@ -363,7 +363,6 @@ Fluxbox::Fluxbox(int argc, char **argv,
363 screens.push_back(i); 363 screens.push_back(i);
364 364
365 // find out, on what "screens" fluxbox should run 365 // find out, on what "screens" fluxbox should run
366 // FIXME(php-coder): maybe it worths moving this code to main.cc, where command line is parsed?
367 for (i = 1; i < m_argc; i++) { 366 for (i = 1; i < m_argc; i++) {
368 if (! strcmp(m_argv[i], "-screen")) { 367 if (! strcmp(m_argv[i], "-screen")) {
369 if ((++i) >= m_argc) { 368 if ((++i) >= m_argc) {
@@ -507,8 +506,11 @@ void Fluxbox::initScreen(BScreen *screen) {
507 506
508 507
509void Fluxbox::eventLoop() { 508void Fluxbox::eventLoop() {
509
510 Display *disp = display(); 510 Display *disp = display();
511
511 while (!m_shutdown) { 512 while (!m_shutdown) {
513
512 if (XPending(disp)) { 514 if (XPending(disp)) {
513 XEvent e; 515 XEvent e;
514 XNextEvent(disp, &e); 516 XNextEvent(disp, &e);
@@ -524,8 +526,9 @@ void Fluxbox::eventLoop() {
524 handleEvent(&e); 526 handleEvent(&e);
525 } 527 }
526 } else { 528 } else {
527 FbTk::Timer::updateTimers(ConnectionNumber(disp)); //handle all timers 529 FbTk::Timer::updateTimers(ConnectionNumber(disp));
528 } 530 }
531
529 } 532 }
530} 533}
531 534
@@ -553,9 +556,11 @@ void Fluxbox::ungrab() {
553} 556}
554 557
555void Fluxbox::handleEvent(XEvent * const e) { 558void Fluxbox::handleEvent(XEvent * const e) {
559
556 _FB_USES_NLS; 560 _FB_USES_NLS;
557 m_last_event = *e; 561 m_last_event = *e;
558 562
563
559 // it is possible (e.g. during moving) for a window 564 // it is possible (e.g. during moving) for a window
560 // to mask all events to go to it 565 // to mask all events to go to it
561 if ((m_masked == e->xany.window) && m_masked_window) { 566 if ((m_masked == e->xany.window) && m_masked_window) {
diff --git a/src/tests/testDemandAttention.cc b/src/tests/testDemandAttention.cc
index 10fadb3..914f369 100644
--- a/src/tests/testDemandAttention.cc
+++ b/src/tests/testDemandAttention.cc
@@ -61,10 +61,7 @@ public:
61 FbTk::RefCount<FbTk::Command<void> > cmd(new FbTk::SimpleCommand<App> 61 FbTk::RefCount<FbTk::Command<void> > cmd(new FbTk::SimpleCommand<App>
62 (*this, 62 (*this,
63 &App::demandAttention)); 63 &App::demandAttention));
64 timeval t; 64 m_timer.setTimeout(5 * FbTk::FbTime::IN_SECONDS);
65 t.tv_sec = 5;
66 t.tv_usec = 0;
67 m_timer.setTimeout(t);
68 m_timer.setCommand(cmd); 65 m_timer.setCommand(cmd);
69 m_timer.fireOnce(false); 66 m_timer.fireOnce(false);
70 m_timer.start(); 67 m_timer.start();
diff --git a/src/tests/titletest.cc b/src/tests/titletest.cc
index 9ea94f1..e16435a 100644
--- a/src/tests/titletest.cc
+++ b/src/tests/titletest.cc
@@ -52,10 +52,7 @@ public:
52 FbTk::RefCount<FbTk::Command> cmd(new FbTk::SimpleCommand<App> 52 FbTk::RefCount<FbTk::Command> cmd(new FbTk::SimpleCommand<App>
53 (*this, 53 (*this,
54 &App::updateTitle)); 54 &App::updateTitle));
55 timeval t; 55 m_timer.setTimeout(150 * FbTk::FbTime::IN_MILLISECONDS);
56 t.tv_sec = 0;
57 t.tv_usec = 150000;
58 m_timer.setTimeout(t);
59 m_timer.setCommand(cmd); 56 m_timer.setCommand(cmd);
60 m_timer.fireOnce(false); 57 m_timer.fireOnce(false);
61 m_timer.start(); 58 m_timer.start();