diff options
| author | Matthias Melcher <fltk@matthiasm.com> | 2016-03-01 00:54:21 +0000 |
|---|---|---|
| committer | Matthias Melcher <fltk@matthiasm.com> | 2016-03-01 00:54:21 +0000 |
| commit | 95824506fe2f410e1cd37e9d2bed58af6f558a0a (patch) | |
| tree | f8c18f415bcdbb1e6e27ecf7c5c754768fc166bd | |
| parent | 6521bb2562c037dbb457bae42970989d1de5b089 (diff) | |
Moved timer code to screen drivers. Not sure if this should be in System Drivers instead.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.3-porting@11253 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
| -rw-r--r-- | FL/Fl_Screen_Driver.H | 6 | ||||
| -rw-r--r-- | src/Fl.cxx | 110 | ||||
| -rw-r--r-- | src/Fl_cocoa.mm | 8 | ||||
| -rw-r--r-- | src/Fl_win32.cxx | 153 | ||||
| -rw-r--r-- | src/drivers/Cocoa/Fl_Cocoa_Screen_Driver.h | 7 | ||||
| -rw-r--r-- | src/drivers/WinAPI/Fl_WinAPI_Screen_Driver.cxx | 143 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Screen_Driver.H | 5 | ||||
| -rw-r--r-- | src/drivers/X11/Fl_X11_Screen_Driver.cxx | 8 |
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)) { |
