Remove deprecated function Fl::set_idle()

This turned out to be more complicated than just to delete a function
because it was used internally, and the callback signatures were a bit
flaky. I also added a lot of documentation to clarify matters.

FL/Fl.H: document idle callback signatures, make some internal
  functions of class Fl private, add public Fl::idle() accessor (read-
  only), add Fl::add_idle(Fl_Old_Idle_Handler cb) to enable using
  old-style idle callbacks w/o 'data' argument.

FL/forms.H: replace Fl::set_idle() with Fl::add_idle().

src/Fl.cxx: rename private Fl::idle_ with trailing underscore.

src/Fl_System_Driver.cxx: use new public accessor Fl::idle() to access
  Fl::idle_ which is now private.

src/Fl_add_idle.cxx: improve documentation, clarify idle callback
  matching, add example code in docs, rename methods,  add overloaded
  Fl::add_idle(Fl_Old_Idle_Handler cb).

src/Fl_win32.cxx: use public Fl::idle() rather than private member.
src/drivers/Unix/Fl_Unix_System_Driver.cxx: same as above.
src/Fl_cocoa.mm: same as above.
This commit is contained in:
Albrecht Schlosser 2025-05-13 21:04:56 +02:00
parent 4d0c1a2a28
commit 9b1379e688
8 changed files with 114 additions and 28 deletions

46
FL/Fl.H
View File

@ -99,10 +99,17 @@ typedef void (*Fl_Timeout_Handler)(void *data);
/** Signature of some wakeup callback functions passed as parameters */
typedef void (*Fl_Awake_Handler)(void *data);
/** Signature of add_idle callback functions passed as parameters */
/** Signature of add_idle callback function passed as parameter.
This signature allows an idle callback to use one parameter as an
arbitrary `data` value.
*/
typedef void (*Fl_Idle_Handler)(void *data);
/** Signature of set_idle callback functions passed as parameters */
/** Signature of add_idle callback function passed as parameter.
This signature allows an idle callback without parameters.
When the callback is called it is called with an additional
parameter (set to nullptr) which is not used by the callback.
*/
typedef void (*Fl_Old_Idle_Handler)();
/** Signature of add_fd functions passed as parameters */
@ -312,6 +319,8 @@ public:
*/
static void option(Fl_Option opt, bool val);
private:
/**
The currently executing idle callback function: DO NOT USE THIS DIRECTLY!
@ -319,7 +328,22 @@ public:
idle callback functions to be called.
\see add_idle(), remove_idle()
*/
static void (*idle)();
static void (*idle_)();
public:
/**
Returns whether at least one idle callback is currently set.
\c true means that at least one callback is currently queued, but
not necessarily active. While a callback is being executed, it is
also counted as "set" unless (i.e. before) it removes itself from
the idle callback queue (ring).
\return whether an idle callback is currently set
\retval true At least one idle callback is currently set.
\retval false No idle callback is currently set.
*/
static bool idle() { return (idle_ != nullptr); }
#ifndef FL_DOXYGEN
private:
@ -491,9 +515,10 @@ public:
static long ticks_since(Fl_Timestamp& then);
static long ticks_between(Fl_Timestamp& back, Fl_Timestamp& further_back);
// private
private:
static void run_idle();
static void run_checks();
public:
static void add_fd(int fd, int when, Fl_FD_Handler cb, void* = 0); // platform dependent
static void add_fd(int fd, Fl_FD_Handler cb, void* = 0); // platform dependent
/** Removes a file descriptor handler. */
@ -504,6 +529,7 @@ public:
static void add_idle(Fl_Idle_Handler cb, void* data = 0);
static int has_idle(Fl_Idle_Handler cb, void* data = 0);
static void remove_idle(Fl_Idle_Handler cb, void* data = 0);
static void add_idle(Fl_Old_Idle_Handler cb);
/** If true then flush() will do something. */
static int damage() {return damage_;}
static void redraw();
@ -1292,12 +1318,18 @@ public:
static int event_button5() {return e_state & FL_BUTTON5;}
/** @} */
private:
/**
Sets an idle callback.
Sets an idle callback (internal use only).
\deprecated This method is obsolete - use the add_idle() method instead.
This method is now private and is used to store the idle callback.
The old, public set_idle() method was deprecated since 1.3.x and
is no longer available in FLTK 1.5.
See documentation: use Fl::add_idle() instead.
*/
static void set_idle(Fl_Old_Idle_Handler cb) {idle = cb;}
static void set_idle_(Fl_Old_Idle_Handler cb) {idle_ = cb;}
public:
/** See grab(Fl_Window*) */
static void grab(Fl_Window& win) {grab(&win);}
/** Releases the current grabbed window, equals grab(0).

View File

@ -170,7 +170,7 @@ inline void fl_add_timeout(long msec, void (*cb)(void*), void* v) {
inline void fl_remove_timeout(int) {}
// type of callback is different!
inline void fl_set_idle_callback(void (*cb)()) {Fl::set_idle(cb);}
inline void fl_set_idle_callback(void (*cb)()) {Fl::add_idle(cb);}
FL_EXPORT Fl_Widget* fl_do_forms(void);
FL_EXPORT Fl_Widget* fl_check_forms();

View File

@ -580,7 +580,7 @@ void fl_trigger_clipboard_notify(int source) {
////////////////////////////////////////////////////////////////
// idle/wait/run/check/ready:
void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions
void (*Fl::idle_)(); // see Fl::add_idle.cxx for the add/remove functions
/*
Private, undocumented method to run idle callbacks.
@ -611,9 +611,9 @@ void (*Fl::idle)(); // see Fl::add_idle.cxx for the add/remove functions
*/
void Fl::run_idle() {
static char in_idle;
if (Fl::idle && !in_idle) {
if (Fl::idle_ && !in_idle) {
in_idle = 1;
Fl::idle();
Fl::idle_(); // call the idle callback stored in Fl::idle_ == Fl::idle()
in_idle = 0;
}
}

View File

@ -1,7 +1,7 @@
//
// A base class for platform specific system calls.
//
// Copyright 1998-2022 by Bill Spitzak and others.
// Copyright 1998-2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -360,9 +360,10 @@ double Fl_System_Driver::wait(double time_to_wait) {
Fl::run_checks();
Fl::run_idle();
// the idle function may turn off idle, we can then wait,
// or it leaves Fl::idle active and we set time_to_wait to 0
if (Fl::idle) {
// The idle function may turn off idle() if *all* idle callbacks
// are removed from the callback queue (ring), we can then wait.
// Or it leaves Fl::idle() active and we set time_to_wait to 0.
if (Fl::idle()) {
time_to_wait = 0.0;
} else {
// limit time by next timer interval

View File

@ -1,7 +1,7 @@
//
// Idle routine support for the Fast Light Tool Kit (FLTK).
//
// Copyright 1998-2022 by Bill Spitzak and others.
// Copyright 1998-2025 by Bill Spitzak and others.
//
// This library is free software. Distribution and use rights are outlined in
// the file "COPYING" which should have been included with this file. If this
@ -15,7 +15,8 @@
//
// Allows you to manage an arbitrary set of idle() callbacks.
// Replaces the older set_idle() call (which is used to implement this)
// Replaces the older set_idle() call which has been renamed to set_idle_(),
// is now private in class Fl::, and is used to implement this.
#include <FL/Fl.H>
@ -25,8 +26,8 @@ struct idle_cb {
idle_cb *next;
};
// the callbacks are stored linked in a ring. last points at the one
// just called, first at the next to call. last->next == first.
// The callbacks are stored linked in a ring. `last` points at the one
// just called, `first` at the next to call. last->next == first.
static idle_cb* first;
static idle_cb* last;
@ -37,7 +38,7 @@ static idle_cb* freelist;
// - adds it as the last entry and
// - calls the idle callback.
// The idle callback may remove itself from the list of idle callbacks
// by calling Fl::remove_idle()
// by calling Fl::remove_idle().
static void call_idle() {
idle_cb* p = first;
@ -49,11 +50,15 @@ static void call_idle() {
Adds a callback function that is called every time by Fl::wait() and also
makes it act as though the timeout is zero (this makes Fl::wait() return
immediately, so if it is in a loop it is called repeatedly, and thus the
idle function is called repeatedly). The idle function can be used to get
idle function is called repeatedly). The idle function can be used to get
background processing done.
You can have multiple idle callbacks. To remove an idle callback use
Fl::remove_idle().
You can have multiple idle callbacks. If this is the case, then all idle
callbacks are called in turn. Each idle callback should return after it
has done \b some work to let the next idle callback or the FLTK event loop
continue processing.
To remove an idle callback use Fl::remove_idle().
Fl::wait() and Fl::check() call idle callbacks, but Fl::ready() does not.
@ -61,6 +66,8 @@ static void call_idle() {
Fl::check(), and Fl::ready().
FLTK will not recursively call the idle callback.
\param[in] cb your idle callback
*/
void Fl::add_idle(Fl_Idle_Handler cb, void* data) {
idle_cb* p = freelist;
@ -75,12 +82,26 @@ void Fl::add_idle(Fl_Idle_Handler cb, void* data) {
} else {
first = last = p;
p->next = p;
set_idle(call_idle);
set_idle_(call_idle);
}
}
void Fl::add_idle(Fl_Old_Idle_Handler cb) {
Fl::add_idle((Fl_Idle_Handler)cb, nullptr);
}
/**
Returns true if the specified idle callback is currently installed.
An idle callback matches the request only if \p data matches the \p data
argument when the callback was installed. There is no "wildcard" search.
\param[in] cb idle callback in question
\param[in] data optional data. Default: zero / nullptr.
\returns Whether the given callback \p cb is queued with \p data.
\retval 1 The callback is currently in the callback queue.
\retval 0 The callback is not queued, or \p data doesn't match.
*/
int Fl::has_idle(Fl_Idle_Handler cb, void* data) {
idle_cb* p = first;
@ -93,6 +114,38 @@ int Fl::has_idle(Fl_Idle_Handler cb, void* data) {
/**
Removes the specified idle callback, if it is installed.
The given idle callback is only removed if \p data matches the
value used when the idle callback was installed. If the idle
callback wants to remove itself, the value provided by the \p data
variable can (and should) be used.
Example for a "one-shot" idle callback, i.e. one that removes itself
when it is called for the first time.
\code
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Button.H>
void idle1(void *data) {
printf("idle1 called with data %4d\n", fl_int(data));
fflush(stdout);
// ... do something ...
Fl::remove_idle(idle1, data);
}
void quit_cb(Fl_Widget *w, void *v) {
w->window()->hide();
}
int main(int argc, char **argv) {
auto window = new Fl_Double_Window(200, 100);
auto button = new Fl_Button(20, 20, 160, 60, "Quit");
button->callback(quit_cb);
window->end();
window->show(argc, argv);
Fl::add_idle(idle1, (void *)1234);
return Fl::run();
}
\endcode
*/
void Fl::remove_idle(Fl_Idle_Handler cb, void* data) {
idle_cb* p = first;
@ -105,7 +158,7 @@ void Fl::remove_idle(Fl_Idle_Handler cb, void* data) {
}
if (l == p) { // only one
first = last = 0;
set_idle(0);
set_idle_(0);
} else {
last = l;
first = l->next = p->next;

View File

@ -865,7 +865,7 @@ double Fl_Darwin_System_Driver::wait(double time_to_wait)
Fl::flush();
if (fl_mac_os_version < 101100) NSEnableScreenUpdates(); // deprecated 10.11
#pragma clang diagnostic pop
if (Fl::idle) // 'idle' may have been set within flush()
if (Fl::idle()) // 'idle' may have been set within flush()
time_to_wait = 0.0;
int retval = do_queued_events(time_to_wait);

View File

@ -396,7 +396,7 @@ double Fl_WinAPI_System_Driver::wait(double time_to_wait) {
}
}
if (Fl::idle || Fl::damage())
if (Fl::idle() || Fl::damage())
time_to_wait = 0.0;
// if there are no more windows and this timer is set

View File

@ -803,7 +803,7 @@ double Fl_Unix_System_Driver::wait(double time_to_wait)
} else {
// do flush first so that user sees the display:
Fl::flush();
if (Fl::idle) // 'idle' may have been set within flush()
if (Fl::idle()) // 'idle_' may have been set within flush()
time_to_wait = 0.0;
else {
Fl_Timeout::elapse_timeouts();