summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--FL/Fl_Screen_Driver.H6
-rw-r--r--src/Fl.cxx110
-rw-r--r--src/Fl_cocoa.mm8
-rw-r--r--src/Fl_win32.cxx153
-rw-r--r--src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h7
-rw-r--r--src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx143
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.H5
-rw-r--r--src/drivers/X11/Fl_X11_Screen_Driver.cxx8
8 files changed, 178 insertions, 262 deletions
diff --git a/FL/Fl_Screen_Driver.H b/FL/Fl_Screen_Driver.H
index 420d555c4..36f52edd2 100644
--- a/FL/Fl_Screen_Driver.H
+++ b/FL/Fl_Screen_Driver.H
@@ -21,6 +21,7 @@
#include <FL/Fl_Device.H>
#include <FL/x.H>
+#include <FL/Fl.H>
// TODO: add text composition?
// TODO: add Fl::display
@@ -84,6 +85,11 @@ public:
virtual int parse_color(const char* p, uchar& r, uchar& g, uchar& b) = 0;
virtual void get_system_colors() = 0;
virtual const char *get_system_scheme();
+ // --- global timers
+ virtual void add_timeout(double time, Fl_Timeout_Handler cb, void *argp) = 0;
+ virtual void repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) = 0;
+ virtual int has_timeout(Fl_Timeout_Handler cb, void *argp) = 0;
+ virtual void remove_timeout(Fl_Timeout_Handler cb, void *argp) = 0;
};
diff --git a/src/Fl.cxx b/src/Fl.cxx
index c086d63e7..60ce50164 100644
--- a/src/Fl.cxx
+++ b/src/Fl.cxx
@@ -334,125 +334,35 @@ int Fl::event_inside(const Fl_Widget *o) /*const*/ {
//
// timer support
//
-
-#ifdef WIN32
-
-// implementation in Fl_win32.cxx
-
-#elif defined(__APPLE__) // PORTME: Fl_Screen_Driver - core stuff from screen, platform, and window driver
-
-// implementation in Fl_cocoa.mm (was Fl_mac.cxx)
-
-#elif defined(FL_PORTING)
-
-# pragma message "FL_PORTING: implement timers in your platform specific core file"
-
-#else
-
-//
-// X11 timers
//
-#if (0) // *FIXME* moved to src/drivers/X11/Fl_X11_Screen_Driver.cxx
-
-////////////////////////////////////////////////////////////////////////
-// 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;
-
-#include <sys/time.h>
-
-// 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;
-
void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
- elapse_timeouts();
- repeat_timeout(time, cb, argp);
+ Fl::screen_driver()->add_timeout(time, cb, argp);
}
void Fl::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;
+ Fl::screen_driver()->repeat_timeout(time, cb, argp);
}
/**
- Returns true if the timeout exists and has not been called yet.
-*/
+ Returns true if the timeout exists and has not been called yet.
+ */
int Fl::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;
+ return Fl::screen_driver()->has_timeout(cb, argp);
}
/**
- Removes a timeout callback. It is harmless to remove a timeout
- callback that no longer exists.
+ 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.
+ \note This version removes all matching timeouts, not just the first one.
This may change in the future.
-*/
+ */
void Fl::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);
- }
- }
+ Fl::screen_driver()->remove_timeout(cb, argp);
}
-#endif // *FIXME* moved to src/drivers/X11/Fl_X11_Screen_Driver.cxx
-#endif
////////////////////////////////////////////////////////////////
// Checks are just stored in a list. They are called in the reverse
diff --git a/src/Fl_cocoa.mm b/src/Fl_cocoa.mm
index 5b70130ad..291efdf19 100644
--- a/src/Fl_cocoa.mm
+++ b/src/Fl_cocoa.mm
@@ -554,7 +554,7 @@ static void do_timer(CFRunLoopTimerRef timer, void* data)
fl_unlock_function();
}
-void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
+void Fl_Cocoa_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
{
// check, if this timer slot exists already
for (int i = 0; i < mac_timer_used; ++i) {
@@ -607,7 +607,7 @@ void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
}
}
-void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
+void Fl_Cocoa_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
{
if (current_timer) {
// k = how many times 'time' seconds after the last scheduled timeout until the future
@@ -623,7 +623,7 @@ void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void* data)
add_timeout(time, cb, data);
}
-int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
+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];
@@ -634,7 +634,7 @@ int Fl::has_timeout(Fl_Timeout_Handler cb, void* data)
return 0;
}
-void Fl::remove_timeout(Fl_Timeout_Handler cb, void* data)
+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];
diff --git a/src/Fl_win32.cxx b/src/Fl_win32.cxx
index 471b7434c..236693db7 100644
--- a/src/Fl_win32.cxx
+++ b/src/Fl_win32.cxx
@@ -1037,44 +1037,6 @@ extern HPALETTE fl_select_palette(void); // in fl_color_win32.cxx
#endif
-/////////////////////////////////////////////////////////////////////////////
-/// Win32 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));
-}
-
-/// END TIMERS
-/////////////////////////////////////////////////////////////////////////////
-
static Fl_Window* resize_bug_fix;
extern void fl_save_pen(void);
@@ -1984,121 +1946,6 @@ Fl_X* Fl_X::make(Fl_Window* w) {
}
-
-
-/////////////////////////////////////////////////////////////////////////////
-/// Win32 timers
-///
-
-
-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::add_timeout(double time, Fl_Timeout_Handler cb, void* data)
-{
- repeat_timeout(time, cb, data);
-}
-
-void Fl::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::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::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);
- }
- }
-}
-
-/// END TIMERS
-/////////////////////////////////////////////////////////////////////////////
-
-
-
////////////////////////////////////////////////////////////////
HINSTANCE fl_display = GetModuleHandle(NULL);
diff --git a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h
index 22c17b165..12dbead09 100644
--- a/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h
+++ b/src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h
@@ -26,7 +26,7 @@
#define FL_COCOA_SCREEN_DRIVER_H
#include <FL/Fl_Screen_Driver.H>
-#include <FL/x.H>
+
/*
Move everything here that manages the native screen interface.
@@ -71,6 +71,11 @@ 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);
};
diff --git a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
index 2ebb2fb4f..3c386223a 100644
--- a/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
+++ b/src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx
@@ -367,6 +367,149 @@ const char *Fl_WinAPI_Screen_Driver::get_system_scheme()
}
+// ---- 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);
+ }
+ }
+}
+
//
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.H b/src/drivers/X11/Fl_X11_Screen_Driver.H
index fc9114c3c..4d107abd1 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.H
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.H
@@ -68,6 +68,11 @@ 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);
};
diff --git a/src/drivers/X11/Fl_X11_Screen_Driver.cxx b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
index 6cf07e380..e168031c2 100644
--- a/src/drivers/X11/Fl_X11_Screen_Driver.cxx
+++ b/src/drivers/X11/Fl_X11_Screen_Driver.cxx
@@ -554,12 +554,12 @@ const char *Fl_X11_Screen_Driver::get_system_scheme()
// X11 timers
//
-void Fl::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
+void Fl_X11_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
elapse_timeouts();
repeat_timeout(time, cb, argp);
}
-void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *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) {
@@ -580,7 +580,7 @@ void Fl::repeat_timeout(double time, Fl_Timeout_Handler cb, void *argp) {
/**
Returns true if the timeout exists and has not been called yet.
*/
-int Fl::has_timeout(Fl_Timeout_Handler cb, void *argp) {
+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;
@@ -593,7 +593,7 @@ int Fl::has_timeout(Fl_Timeout_Handler cb, void *argp) {
\note This version removes all matching timeouts, not just the first one.
This may change in the future.
*/
-void Fl::remove_timeout(Fl_Timeout_Handler cb, void *argp) {
+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)) {