summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorAlbrecht Schlosser <albrechts.fltk@online.de>2022-01-31 22:27:17 +0100
committerGitHub <noreply@github.com>2022-01-31 22:27:17 +0100
commit29d9e31c51e6c11d6e33abf9bc4551afd9de3836 (patch)
tree82dcb5f84dde9bb6cbfe50983094baa12215e57e /src/drivers
parentcf4a832e6a801b46c38f6236369c74056e8f89ec (diff)
Consolidate timeout handling across platforms (#379)
Add Fl_Timeout class Move platform independent code of Fl::wait() to main part - basic timeout handling - Fl::run_checks() - Fl::run_idle() - Fl::idle() - waiting time calculation (next timeout) - remove platform dependent "screen driver" stuff
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H7
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx142
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H10
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx145
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.H5
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.cxx161
6 files changed, 14 insertions, 456 deletions
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
index dcd5c4f57..7dd6fc14a 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
+++ b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.H
@@ -2,7 +2,7 @@
// Definition of Apple Cocoa Screen interface
// for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2018 by Bill Spitzak and others.
+// Copyright 2010-2022 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
@@ -80,11 +80,6 @@ public:
virtual void grab(Fl_Window* win);
// --- global colors
virtual void get_system_colors();
- // --- global timers
- virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
- virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
virtual int has_marked_text() const;
static void reset_marked_text();
static void insertion_point_location(int x, int y, int height);
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
index 1a36149e2..e213e5fd0 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
+++ b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.cxx
@@ -1,7 +1,7 @@
//
// Definition of Apple Cocoa Screen interface.
//
-// Copyright 1998-2018 by Bill Spitzak and others.
+// Copyright 1998-2022 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
@@ -401,143 +401,3 @@ Fl_RGB_Image *Fl_Cocoa_Screen_Driver::read_win_rectangle(int X, int Y, int w, in
rgb->alloc_array = 1;
return rgb;
}
-
-//
-// MacOS X timers
-//
-
-struct MacTimeout {
- Fl_Timeout_Handler callback;
- void* data;
- CFRunLoopTimerRef timer;
- char pending;
- CFAbsoluteTime next_timeout; // scheduled time for this timer
-};
-static MacTimeout* mac_timers;
-static int mac_timer_alloc;
-static int mac_timer_used;
-static MacTimeout* current_timer; // the timer that triggered its callback function
-
-static void realloc_timers()
-{
- if (mac_timer_alloc == 0) {
- mac_timer_alloc = 8;
- fl_open_display(); // needed because the timer creates an event
- }
- mac_timer_alloc *= 2;
- MacTimeout* new_timers = new MacTimeout[mac_timer_alloc];
- memset(new_timers, 0, sizeof(MacTimeout)*mac_timer_alloc);
- memcpy(new_timers, mac_timers, sizeof(MacTimeout) * mac_timer_used);
- if (current_timer) {
- MacTimeout* newCurrent = new_timers + (current_timer - mac_timers);
- current_timer = newCurrent;
- }
- MacTimeout* delete_me = mac_timers;
- mac_timers = new_timers;
- delete [] delete_me;
-}
-
-static void delete_timer(MacTimeout& t)
-{
- if (t.timer) {
- CFRunLoopRemoveTimer(CFRunLoopGetCurrent(),
- t.timer,
- kCFRunLoopDefaultMode);
- CFRelease(t.timer);
- memset(&t, 0, sizeof(MacTimeout));
- }
-}
-
-static void do_timer(CFRunLoopTimerRef timer, void* data)
-{
- fl_lock_function();
- fl_intptr_t timerId = (fl_intptr_t)data;
- current_timer = &mac_timers[timerId];
- current_timer->pending = 0;
- (current_timer->callback)(current_timer->data);
- if (current_timer && current_timer->pending == 0)
- delete_timer(*current_timer);
- current_timer = NULL;
-
- Fl_Cocoa_Screen_Driver::breakMacEventLoop();
- fl_unlock_function();
-}
-
-void Fl_Cocoa_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
-{
- // always create a new timer entry
- fl_intptr_t timer_id = -1;
- // find an empty slot in the timer array
- for (int i = 0; i < mac_timer_used; ++i) {
- if ( !mac_timers[i].timer ) {
- timer_id = i;
- break;
- }
- }
- // if there was no empty slot, append a new timer
- if (timer_id == -1) {
- // make space if needed
- if (mac_timer_used == mac_timer_alloc) {
- realloc_timers();
- }
- timer_id = mac_timer_used++;
- }
- // now install a brand new timer
- MacTimeout& t = mac_timers[timer_id];
- CFRunLoopTimerContext context = {0, (void*)timer_id, NULL,NULL,NULL};
- CFRunLoopTimerRef timerRef = CFRunLoopTimerCreate(kCFAllocatorDefault,
- CFAbsoluteTimeGetCurrent() + time,
- 1E30,
- 0,
- 0,
- do_timer,
- &context
- );
- if (timerRef) {
- CFRunLoopAddTimer(CFRunLoopGetCurrent(),
- timerRef,
- kCFRunLoopDefaultMode);
- t.callback = cb;
- t.data = data;
- t.timer = timerRef;
- t.pending = 1;
- t.next_timeout = CFRunLoopTimerGetNextFireDate(timerRef);
- }
-}
-
-void Fl_Cocoa_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
-{
- if (!current_timer) {
- add_timeout(time, cb, data);
- return;
- }
- // k = how many times 'time' seconds after the last scheduled timeout until the future
- double k = ceil( (CFAbsoluteTimeGetCurrent() - current_timer->next_timeout) / time);
- if (k < 1) k = 1;
- current_timer->next_timeout += k * time;
- CFRunLoopTimerSetNextFireDate(current_timer->timer, current_timer->next_timeout );
- current_timer->callback = cb;
- current_timer->data = data;
- current_timer->pending = 1;
-}
-
-int Fl_Cocoa_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void* data)
-{
- for (int i = 0; i < mac_timer_used; ++i) {
- MacTimeout& t = mac_timers[i];
- if (t.callback == cb && t.data == data && t.pending) {
- return 1;
- }
- }
- return 0;
-}
-
-void Fl_Cocoa_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void* data)
-{
- for (int i = 0; i < mac_timer_used; ++i) {
- MacTimeout& t = mac_timers[i];
- if (t.callback == cb && ( t.data == data || data == NULL)) {
- delete_timer(t);
- }
- }
-}
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
index 9bd8485a3..c621f7e5e 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.H
@@ -1,8 +1,7 @@
//
-// Definition of Windows screen interface
-// for the Fast Light Tool Kit (FLTK).
+// Windows screen interface for the Fast Light Tool Kit (FLTK).
//
-// Copyright 2010-2018 by Bill Spitzak and others.
+// Copyright 2010-2022 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
@@ -67,11 +66,6 @@ public:
virtual void grab(Fl_Window* win);
// --- global colors
virtual void get_system_colors();
- // --- global timers
- virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
- virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
virtual int dnd(int unused);
virtual int compose(int &del);
virtual Fl_RGB_Image *read_win_rectangle(int X, int Y, int w, int h, Fl_Window *win, bool may_capture_subwins, bool *did_capture_subwins);
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index 5747f16a4..489e7fe8d 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -1,7 +1,7 @@
//
// Windows screen interface for the Fast Light Tool Kit (FLTK).
//
-// Copyright 1998-2018 by Bill Spitzak and others.
+// Copyright 1998-2022 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
@@ -328,149 +328,6 @@ void Fl_WinAPI_Screen_Driver::get_system_colors()
}
-// ---- timers
-
-
-struct Win32Timer
-{
- UINT_PTR handle;
- Fl_Timeout_Handler callback;
- void *data;
-};
-static Win32Timer* win32_timers;
-static int win32_timer_alloc;
-static int win32_timer_used;
-static HWND s_TimerWnd;
-
-
-static void realloc_timers()
-{
- if (win32_timer_alloc == 0) {
- win32_timer_alloc = 8;
- }
- win32_timer_alloc *= 2;
- Win32Timer* new_timers = new Win32Timer[win32_timer_alloc];
- memset(new_timers, 0, sizeof(Win32Timer) * win32_timer_used);
- memcpy(new_timers, win32_timers, sizeof(Win32Timer) * win32_timer_used);
- Win32Timer* delete_me = win32_timers;
- win32_timers = new_timers;
- delete [] delete_me;
-}
-
-
-static void delete_timer(Win32Timer& t)
-{
- KillTimer(s_TimerWnd, t.handle);
- memset(&t, 0, sizeof(Win32Timer));
-}
-
-
-static LRESULT CALLBACK s_TimerProc(HWND hwnd, UINT msg,
- WPARAM wParam, LPARAM lParam)
-{
- switch (msg) {
- case WM_TIMER:
- {
- unsigned int id = (unsigned) (wParam - 1);
- if (id < (unsigned int)win32_timer_used && win32_timers[id].handle) {
- Fl_Timeout_Handler cb = win32_timers[id].callback;
- void* data = win32_timers[id].data;
- delete_timer(win32_timers[id]);
- if (cb) {
- (*cb)(data);
- }
- }
- }
- return 0;
-
- default:
- break;
- }
- return DefWindowProc(hwnd, msg, wParam, lParam);
-}
-
-
-void Fl_WinAPI_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
-{
- repeat_timeout(time, cb, data);
-}
-
-
-void Fl_WinAPI_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
-{
- int timer_id = -1;
- for (int i = 0; i < win32_timer_used; ++i) {
- if ( !win32_timers[i].handle ) {
- timer_id = i;
- break;
- }
- }
- if (timer_id == -1) {
- if (win32_timer_used == win32_timer_alloc) {
- realloc_timers();
- }
- timer_id = win32_timer_used++;
- }
- unsigned int elapsed = (unsigned int)(time * 1000);
-
- if ( !s_TimerWnd ) {
- const char* timer_class = "FLTimer";
- WNDCLASSEX wc;
- memset(&wc, 0, sizeof(wc));
- wc.cbSize = sizeof (wc);
- wc.style = CS_CLASSDC;
- wc.lpfnWndProc = (WNDPROC)s_TimerProc;
- wc.hInstance = fl_display;
- wc.lpszClassName = timer_class;
- /*ATOM atom =*/ RegisterClassEx(&wc);
- // create a zero size window to handle timer events
- s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
- timer_class, "",
- WS_POPUP,
- 0, 0, 0, 0,
- NULL, NULL, fl_display, NULL);
- // just in case this OS won't let us create a 0x0 size window:
- if (!s_TimerWnd)
- s_TimerWnd = CreateWindowEx(WS_EX_LEFT | WS_EX_TOOLWINDOW,
- timer_class, "",
- WS_POPUP,
- 0, 0, 1, 1,
- NULL, NULL, fl_display, NULL);
- ShowWindow(s_TimerWnd, SW_SHOWNOACTIVATE);
- }
-
- win32_timers[timer_id].callback = cb;
- win32_timers[timer_id].data = data;
-
- win32_timers[timer_id].handle =
- SetTimer(s_TimerWnd, timer_id + 1, elapsed, NULL);
-}
-
-
-int Fl_WinAPI_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void* data)
-{
- for (int i = 0; i < win32_timer_used; ++i) {
- Win32Timer& t = win32_timers[i];
- if (t.handle && t.callback == cb && t.data == data) {
- return 1;
- }
- }
- return 0;
-}
-
-
-void Fl_WinAPI_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void* data)
-{
- int i;
- for (i = 0; i < win32_timer_used; ++i) {
- Win32Timer& t = win32_timers[i];
- if (t.handle && t.callback == cb &&
- (t.data == data || data == NULL)) {
- delete_timer(t);
- }
- }
-}
-
int Fl_WinAPI_Screen_Driver::compose(int &del) {
unsigned char ascii = (unsigned char)Fl::e_text[0];
int condition = (Fl::e_state & (FL_ALT | FL_META)) && !(ascii & 128) ;
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.H b/src/drivers/X11/Fl_X11_Screen_Driver.H
index 7d665dbb4..c8676f347 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.H
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.H
@@ -85,11 +85,6 @@ public:
virtual int parse_color(const char* p, uchar& r, uchar& g, uchar& b);
virtual void get_system_colors();
virtual const char *get_system_scheme();
- // --- global timers
- virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp);
- virtual int has_timeout(Fl_Timeout_Handler cb, void *argp);
- virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp);
virtual int dnd(int unused);
virtual int compose(int &del);
virtual void compose_reset();
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
index beb30df83..3e7edf872 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
@@ -31,6 +31,8 @@
#include <FL/filename.H>
#include <sys/time.h>
+#include "../../Fl_Timeout.h"
+
#if HAVE_XINERAMA
# include <X11/extensions/Xinerama.h>
#endif
@@ -55,52 +57,6 @@ extern const char *fl_bg;
extern const char *fl_bg2;
// end of extern additions workaround
-//
-// X11 timers
-//
-
-
-////////////////////////////////////////////////////////////////////////
-// Timeouts are stored in a sorted list (*first_timeout), so only the
-// first one needs to be checked to see if any should be called.
-// Allocated, but unused (free) Timeout structs are stored in another
-// linked list (*free_timeout).
-
-struct Timeout {
- double time;
- void (*cb)(void*);
- void* arg;
- Timeout* next;
-};
-static Timeout* first_timeout, *free_timeout;
-
-// I avoid the overhead of getting the current time when we have no
-// timeouts by setting this flag instead of getting the time.
-// In this case calling elapse_timeouts() does nothing, but records
-// the current time, and the next call will actually elapse time.
-static char reset_clock = 1;
-
-static void elapse_timeouts() {
- static struct timeval prevclock;
- struct timeval newclock;
- gettimeofday(&newclock, NULL);
- double elapsed = newclock.tv_sec - prevclock.tv_sec +
- (newclock.tv_usec - prevclock.tv_usec)/1000000.0;
- prevclock.tv_sec = newclock.tv_sec;
- prevclock.tv_usec = newclock.tv_usec;
- if (reset_clock) {
- reset_clock = 0;
- } else if (elapsed > 0) {
- for (Timeout* t = first_timeout; t; t = t->next) t->time -= elapsed;
- }
-}
-
-
-// Continuously-adjusted error value, this is a number <= 0 for how late
-// we were at calling the last timeout. This appears to make repeat_timeout
-// very accurate even when processing takes a significant portion of the
-// time interval:
-static double missed_timeout_by;
/**
Creates a driver that manages all screen and display related calls.
@@ -411,39 +367,6 @@ void Fl_X11_Screen_Driver::flush()
double Fl_X11_Screen_Driver::wait(double time_to_wait)
{
- static char in_idle;
-
- if (first_timeout) {
- elapse_timeouts();
- Timeout *t;
- while ((t = first_timeout)) {
- if (t->time > 0) break;
- // The first timeout in the array has expired.
- missed_timeout_by = t->time;
- // We must remove timeout from array before doing the callback:
- void (*cb)(void*) = t->cb;
- void *argp = t->arg;
- first_timeout = t->next;
- t->next = free_timeout;
- free_timeout = t;
- // Now it is safe for the callback to do add_timeout:
- cb(argp);
- }
- } else {
- reset_clock = 1; // we are not going to check the clock
- }
- Fl::run_checks();
- if (Fl::idle) {
- if (!in_idle) {
- in_idle = 1;
- Fl::idle();
- in_idle = 0;
- }
- // the idle function may turn off idle, we can then wait:
- if (Fl::idle) time_to_wait = 0.0;
- }
- if (first_timeout && first_timeout->time < time_to_wait)
- time_to_wait = first_timeout->time;
if (time_to_wait <= 0.0) {
// do flush second so that the results of events are visible:
int ret = this->poll_or_select_with_delay(0.0);
@@ -452,25 +375,20 @@ double Fl_X11_Screen_Driver::wait(double time_to_wait)
} else {
// do flush first so that user sees the display:
Fl::flush();
- if (Fl::idle && !in_idle) // 'idle' may have been set within flush()
+ if (Fl::idle) // 'idle' may have been set within flush()
time_to_wait = 0.0;
- else if (first_timeout && first_timeout->time < time_to_wait) {
- // another timeout may have been queued within flush(), see STR #3188
- time_to_wait = first_timeout->time >= 0.0 ? first_timeout->time : 0.0;
+ else {
+ Fl_Timeout::elapse_timeouts();
+ time_to_wait = Fl_Timeout::time_to_wait(time_to_wait);
}
return this->poll_or_select_with_delay(time_to_wait);
}
}
-int Fl_X11_Screen_Driver::ready()
-{
- if (first_timeout) {
- elapse_timeouts();
- if (first_timeout->time <= 0) return 1;
- } else {
- reset_clock = 1;
- }
+int Fl_X11_Screen_Driver::ready() {
+ Fl_Timeout::elapse_timeouts();
+ if (Fl_Timeout::time_to_wait(1.0) <= 0.0) return 1;
return this->poll_or_select();
}
@@ -598,67 +516,6 @@ const char *Fl_X11_Screen_Driver::get_system_scheme()
return s;
}
-// ###################### *FIXME* ########################
-// ###################### *FIXME* ########################
-// ###################### *FIXME* ########################
-
-
-//
-// X11 timers
-//
-
-void Fl_X11_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
- elapse_timeouts();
- missed_timeout_by = 0;
- repeat_timeout(time, cb, argp);
-}
-
-void Fl_X11_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
- time += missed_timeout_by; if (time < -.05) time = 0;
- Timeout* t = free_timeout;
- if (t) {
- free_timeout = t->next;
- } else {
- t = new Timeout;
- }
- t->time = time;
- t->cb = cb;
- t->arg = argp;
- // insert-sort the new timeout:
- Timeout** p = &first_timeout;
- while (*p && (*p)->time <= time) p = &((*p)->next);
- t->next = *p;
- *p = t;
-}
-
-/**
- Returns true if the timeout exists and has not been called yet.
-*/
-int Fl_X11_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *argp) {
- for (Timeout* t = first_timeout; t; t = t->next)
- if (t->cb == cb && t->arg == argp) return 1;
- return 0;
-}
-
-/**
- Removes a timeout callback. It is harmless to remove a timeout
- callback that no longer exists.
-
- \note This version removes all matching timeouts, not just the first one.
- This may change in the future.
-*/
-void Fl_X11_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *argp) {
- for (Timeout** p = &first_timeout; *p;) {
- Timeout* t = *p;
- if (t->cb == cb && (t->arg == argp || !argp)) {
- *p = t->next;
- t->next = free_timeout;
- free_timeout = t;
- } else {
- p = &(t->next);
- }
- }
-}
int Fl_X11_Screen_Driver::compose(int& del) {
int condition;