diff options
| author | Albrecht Schlosser <albrechts.fltk@online.de> | 2025-05-13 21:04:56 +0200 |
|---|---|---|
| committer | Albrecht Schlosser <albrechts.fltk@online.de> | 2025-05-13 21:08:51 +0200 |
| commit | 9b1379e6888abc7cc051a6c82d8b27ce454ceb5a (patch) | |
| tree | e3256c9936097166efac395a2411eba4e8da5f34 | |
| parent | 4d0c1a2a289556eacc63fd407fb77d8190be0b1f (diff) | |
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.
| -rw-r--r-- | FL/Fl.H | 46 | ||||
| -rw-r--r-- | FL/forms.H | 2 | ||||
| -rw-r--r-- | src/Fl.cxx | 6 | ||||
| -rw-r--r-- | src/Fl_System_Driver.cxx | 9 | ||||
| -rw-r--r-- | src/Fl_add_idle.cxx | 73 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 2 | ||||
| -rw-r--r-- | src/Fl_win32.cxx | 2 | ||||
| -rw-r--r-- | src/drivers/Unix/Fl_Unix_System_Driver.cxx | 2 |
8 files changed, 114 insertions, 28 deletions
@@ -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). + + 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. - \deprecated This method is obsolete - use the add_idle() method instead. + 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). diff --git a/FL/forms.H b/FL/forms.H index 9523b4da5..076c54d6f 100644 --- a/FL/forms.H +++ b/FL/forms.H @@ -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(); diff --git a/src/Fl.cxx b/src/Fl.cxx index bae7f1328..b1c38caf6 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -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; } } diff --git a/src/Fl_System_Driver.cxx b/src/Fl_System_Driver.cxx index 7cac84faf..5a01d6534 100644 --- a/src/Fl_System_Driver.cxx +++ b/src/Fl_System_Driver.cxx @@ -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 diff --git a/src/Fl_add_idle.cxx b/src/Fl_add_idle.cxx index 1f1673f36..50e34780a 100644 --- a/src/Fl_add_idle.cxx +++ b/src/Fl_add_idle.cxx @@ -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; diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm index 2b8ebd7aa..19aa86791 100644 --- a/src/Fl_cocoa.mm +++ b/src/Fl_cocoa.mm @@ -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); diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx index d7681c96d..84cb6649d 100644 --- a/src/Fl_win32.cxx +++ b/src/Fl_win32.cxx @@ -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 diff --git a/src/drivers/Unix/Fl_Unix_System_Driver.cxx b/src/drivers/Unix/Fl_Unix_System_Driver.cxx index f1d846842..2b15882a1 100644 --- a/src/drivers/Unix/Fl_Unix_System_Driver.cxx +++ b/src/drivers/Unix/Fl_Unix_System_Driver.cxx @@ -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(); |
