What's the difference between repeat_timeout and add_timout?

54 views
Skip to first unread message

Heart Bleed

unread,
Mar 29, 2025, 8:13:22 AM3/29/25
to fltk.general
Hello ,

Can anyone please tell me what is basic difference between repeat_timeout and add_timout? my confusion stems from the fact that add_timeout can be recursively called back in callback function itself . But I see this code from https://www.seriss.com/people/erco/fltk/#Animate

void ShowNextImage_CB(void*) {
    static int x = 0;
    grp->image(jpgs[x++ % TOTAL]);
    win->redraw();
    // Fl::repeat_timeout(RATE, ShowNextImage_CB);                      // steady rate
    Fl::repeat_timeout(((x%TOTAL)==0)?2.0:RATE, ShowNextImage_CB);      // eye blink: hold 0003.jpg for 2 secs
}

I have had no exposure to GUI hence these questions. I'm trying to learn the cases/application for these two maybe?

Regards and Thanks a lot

Gonzalo Garramuño

unread,
Mar 29, 2025, 9:01:21 AM3/29/25
to fltkg...@googlegroups.com

El 29/3/25 a las 09:13, Heart Bleed escribió:
> Hello ,
>
> Can anyone please tell me what is basic difference
> between repeat_timeout and add_timout?

add_timeout adds a single timeout call to the FLTK queue.

repeat_timeout's main purpose is to be called from the callback and it
also adds a timeout to the queue BUT it checks previous
repeat/add_timeout's to try to make it more accurate.  repeat timeout
allows you to do calls that have milliseconds precision.


--
Gonzalo Garramuño
ggar...@gmail.com

Heart Bleed

unread,
Mar 29, 2025, 9:15:17 AM3/29/25
to fltk.general
Fl::add_timeout(((x % TOTAL) == 0) ? 2.0 : RATE, ShowNextImage_CB); so this won't work? 

Thank for helping me

Albrecht Schlosser

unread,
Mar 29, 2025, 10:35:10 AM3/29/25
to fltkg...@googlegroups.com
On 3/29/25 14:15 Heart Bleed wrote:
Fl::add_timeout(((x % TOTAL) == 0) ? 2.0 : RATE, ShowNextImage_CB); so this won't work?

It does work, but maybe with less precision.

As Gonzalo wrote, Fl::repeat_timeout is intended to be called from a timeout callback. It takes into account the delay that may have happened before the callback was actually called and the time the callback used before Fl::repeat_timeout is called.

A simple example with pseudo code (the callback only):

void timer_cb(...) {
  // do something that takes a variant time...
  sleep(100);                    // sleep 100 ms (note: pseudo code!)
  Fl::repeat_timeout(1.0, ...);  // callback should be every 1.0 seconds#
}

This code will trigger the timeout (callback) as accurately as possible, very close to every 1.0 seconds.

If you replace 'repeat_timeout' with 'add_timeout' the callback will be triggered about every 1.1 seconds.

I hope this clarifies it. See also the docs with example code here:
https://www.fltk.org/doc-1.4/classFl.html#a46e5695dca672130f615c438f2a067a3

Hint: run the example code, add an appropriate 'sleep' method (depending on your platform), and test again (you could add up to 0.9 seconds to see the effect. It should still be about every second. Then replace `Fl::repeat_timeout(1.0, callback);` with `Fl::add_timeout(1.0, callback);` and watch the difference...

Heart Bleed

unread,
Mar 29, 2025, 11:06:32 AM3/29/25
to fltk.general
Thanks a lot sir. Now I understand it better.

Heart Bleed

unread,
Mar 30, 2025, 2:46:00 PM3/30/25
to fltk.general
Hi sorry to ask (I couldn't find all this info in docs :| ), but can anyone please tell me if drawing function work relative to parent widget's x and y coordinates? I can pass them negative coordinates?

Albrecht Schlosser

unread,
Mar 30, 2025, 2:58:40 PM3/30/25
to fltkg...@googlegroups.com
On 3/30/25 20:46 Heart Bleed wrote:
> Hi sorry to ask (I couldn't find all this info in docs :| ), but can
> anyone please tell me if drawing function work relative to parent
> widget's x and y coordinates?

All drawing functions work with coordinates relative to the parent
*window* of the widget. The widget's x() and y() coordinates can be used
to draw relative to x() and y().

> I can pass them negative coordinates?

Negative coordinates would be outside the window and thus useless
because drawing outside the window would be clipped.

More details to coordinates can be found in the docs:
https://www.fltk.org/doc-1.4/coordinates.html


PS: please use a new thread with an adequate title for each new question
in the future.

Matthias Melcher

unread,
Mar 30, 2025, 4:20:28 PM3/30/25
to fltk.general
Albrecht-S schrieb am Samstag, 29. März 2025 um 15:35:10 UTC+1:
On 3/29/25 14:15 Heart Bleed wrote:
Fl::add_timeout(((x % TOTAL) == 0) ? 2.0 : RATE, ShowNextImage_CB); so this won't work?
It does work, but maybe with less precision.
(...) 
void timer_cb(...) { // do something that takes a variant time...   sleep(100);  // sleep 100 ms (note: pseudo code!) Fl::repeat_timeout(1.0, ...); // callback should be every 1.0 seconds# }
 A common problem when writing timing based apps, a game for example, is finding a base time. Rendering graphics is not reliably faster than the frame rate you may want, especially if the host computer is busy with other tasks at the same time. A time base is a quite common request, so FLTK has a call for that.

At the start of your animation, get a timestamp by calling Fl::now(), and then whenever your callback if called from Fl::repeat_timeout(),  call Fl::seconds_since(...), and FLTK will return the time that elapsed between launching you animation and when the callback is actually called. The timer resolution is in fractions of a second and should be sufficient for most games. Since this is so common, we even have Fl::ticks_since() which returns the elapsed time in frames, assuming 60fps as a base.


Here is a stopwatch example:


#include <FL/Fl.H>

#include <FL/Fl_Window.H>

#include <FL/Fl_Box.H>


Fl_Window *win;

Fl_Box *box;

Fl_Timestamp start;


void timer_cb(void*) {

  // we want 25 frames per second, but here we ask for the time that actually elapsed

  char text[80];

  snprintf(text, 79, "%f seconds since start", Fl::seconds_since(start));

  box->copy_label(text);

  box->redraw();

  // Now we may do some time consuming things here that take more than 1/25th of a second

  Fl::repeat_timeout(1.0/20.0, timer_cb); // but ideally we want 25 redraws per second

}


int main(int argc, char** argv) {

  win = new Fl_Window(400, 100);

  box = new Fl_Box(10, 10, 380, 80);

  box->labelfont(FL_COURIER);

  win->show(argc, argv);

  start = Fl::now();

  Fl::add_timeout(1.0, timer_cb);

  Fl::run();

}



humpty

unread,
Apr 7, 2025, 12:26:02 PM4/7/25
to fltk.general
Am I right in thinking that 
Fl::repeat_timeout calculates the time from the start of the function
while 
Fl::add_timeout calculates the time from the call of Fl::add_timeout ?

Also, if  "do some time consuming things"  takes longer than the timeout,
does Fl::repeat_timeout fire immediately ?

Albrecht Schlosser

unread,
Apr 8, 2025, 7:42:30 AM4/8/25
to fltkg...@googlegroups.com
On 4/7/25 18:26 humpty wrote:
Am I right in thinking that 
Fl::repeat_timeout calculates the time from the start of the function
while 
Fl::add_timeout calculates the time from the call of Fl::add_timeout ?

Almost, but not completely correct. The latter is correct, i.e. Fl::add_timeout calculates the time from the call of Fl::add_timeout.

Regarding Fl::repeat_timeout(): it calculates the time from the time the original timer was due. The difference to what you wrote ("the time from the start of the function") is that the call of "the function" (I assume you mean the timer callback) can already be delayed due to other events and timer callbacks being called.


Also, if  "do some time consuming things"  takes longer than the timeout,
does Fl::repeat_timeout fire immediately ?

Not immediately in the sense that the callback is called when you schedule it by calling Fl::repeat_timeout(), but as soon as possible when the next round of timer and/or event processing is done. Technically the timer callback is queued immediately but processed later when time permits. There's also an exception: if the "time consuming things" take too long, such that the calculated timeout time would be negative (or zero) a small positive timer delay is used, hence this and all consecutive timers will be delayed more than they are intended. You should always return from a timer callback as soon as possible, but if the processing time is too long, then this is what happens.

Reply all
Reply to author
Forward
0 new messages