summaryrefslogtreecommitdiff
path: root/src/drivers/Android/Fl_Android_Screen_Driver.cxx
diff options
context:
space:
mode:
authorMatthias Melcher <fltk@matthiasm.com>2018-03-12 20:10:49 +0000
committerMatthias Melcher <fltk@matthiasm.com>2018-03-12 20:10:49 +0000
commitb0a514366eed9b5ef4d7f99768af0d7e89755728 (patch)
tree7c175f0e1ade365bd2a259286c803f40f9bb2618 /src/drivers/Android/Fl_Android_Screen_Driver.cxx
parent1b52ead802e1f3b24c33cadacb8d67dbfb209253 (diff)
Android: added support for Fl::add_timeout() and friends.
git-svn-id: file:///fltk/svn/fltk/branches/branch-1.4@12742 ea41ed52-d2ee-0310-a9c1-e6b18d33e121
Diffstat (limited to 'src/drivers/Android/Fl_Android_Screen_Driver.cxx')
-rw-r--r--src/drivers/Android/Fl_Android_Screen_Driver.cxx304
1 files changed, 163 insertions, 141 deletions
diff --git a/src/drivers/Android/Fl_Android_Screen_Driver.cxx b/src/drivers/Android/Fl_Android_Screen_Driver.cxx
index 810ccedbf..545d8b979 100644
--- a/src/drivers/Android/Fl_Android_Screen_Driver.cxx
+++ b/src/drivers/Android/Fl_Android_Screen_Driver.cxx
@@ -27,12 +27,17 @@
#include <FL/Fl_RGB_Image.H>
#include <FL/fl_ask.H>
#include <stdio.h>
+#include <errno.h>
+#include <math.h>
static void nothing() {}
void (*fl_unlock_function)() = nothing;
void (*fl_lock_function)() = nothing;
+static void timer_do_callback(int timerIndex);
+
+
#if 0
// these are set by Fl::args() and override any system colors: from Fl_get_system_colors.cxx
@@ -95,7 +100,7 @@ int Fl_Android_Screen_Driver::handle_input_event()
consumed = handle_mouse_event(event);
break;
default:
- // don;t do anything. There may be additional event types in the future
+ // don't do anything. There may be additional event types in the future
break;
}
// TODO: handle all events here
@@ -178,6 +183,9 @@ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
case Fl_Android_Application::LOOPER_ID_INPUT:
ret = handle_input_event();
break;
+ case Fl_Android_Application::LOOPER_ID_TIMER:
+ timer_do_callback(Fl_Android_Application::receive_timer_index());
+ break;
case -3: return ret;
default: return ret;
}
@@ -186,6 +194,14 @@ int Fl_Android_Screen_Driver::handle_queued_events(double time_to_wait)
}
+// TODO: we need a timout: nsecs_t systemTime(int clock = SYSTEM_TIME_MONOTONIC);
+// static inline nsecs_t seconds_to_nanoseconds(nsecs_t secs) return secs*1000000000;
+// int timer_create(clockid_t __clock, struct sigevent* __event, timer_t* __timer_ptr);
+// int timer_delete(timer_t __timer);
+// int timer_settime(timer_t __timer, int __flags, const struct itimerspec* __new_value, struct itimerspec* __old_value);
+// int timer_gettime(timer_t __timer, struct itimerspec* __ts);
+// int timer_getoverrun(timer_t __timer);
+
double Fl_Android_Screen_Driver::wait(double time_to_wait)
{
Fl::run_checks();
@@ -514,149 +530,9 @@ 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);
- }
- }
-}
-
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) ;
@@ -832,6 +708,152 @@ int Fl_WinAPI_Screen_Driver::screen_num_unscaled(int x, int y)
#endif
+
+// ---- timers
+
+struct TimerData
+{
+ timer_t handle;
+ struct sigevent sigevent;
+ Fl_Timeout_Handler callback;
+ void *data;
+ bool used;
+ bool triggered;
+};
+static TimerData* timerData = 0L;
+static int NTimerData = 0;
+static int nTimerData = 0;
+
+
+static int allocate_more_timers()
+{
+ if (NTimerData == 0) {
+ NTimerData = 8;
+ }
+ if (NTimerData>256) { // out of timers
+ return -1;
+ }
+ NTimerData *= 2;
+ timerData = (TimerData*)realloc(timerData, sizeof(TimerData) * NTimerData);
+ return nTimerData;
+}
+
+
+static void timer_signal_handler(union sigval data)
+{
+ int timerIndex = data.sival_int;
+ Fl_Android_Application::send_timer_index(timerIndex);
+}
+
+
+static void timer_do_callback(int timerIndex)
+{
+ TimerData& t = timerData[timerIndex];
+ t.triggered = false;
+ if (t.callback) {
+ t.callback(t.data);
+ // TODO: should we release the timer at this point?
+ }
+}
+
+
+void Fl_Android_Screen_Driver::add_timeout(double time, Fl_Timeout_Handler cb, void *data)
+{
+ repeat_timeout(time, cb, data);
+}
+
+
+void Fl_Android_Screen_Driver::repeat_timeout(double time, Fl_Timeout_Handler cb, void *data)
+{
+ int ret = -1;
+ int timerIndex = -1;
+
+ // first, find the timer associated with this handler
+ for (int i = 0; i < nTimerData; ++i) {
+ TimerData& t = timerData[i];
+ if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
+ timerIndex = i;
+ break;
+ }
+ }
+
+ // if we did not have a timer yet, find a free slot
+ if (timerIndex==-1) {
+ for (int i = 0; i < nTimerData; ++i) {
+ if (!timerData[i].used)
+ timerIndex = i;
+ break;
+ }
+ }
+
+ // if that didn't work, allocate more timers
+ if (timerIndex==-1) {
+ if (nTimerData==NTimerData)
+ allocate_more_timers();
+ timerIndex = nTimerData++;
+ }
+
+ // if that didn;t work either, we ran out of timers
+ if (timerIndex==-1) {
+ Fl::error("FLTK ran out of timer slots.");
+ return;
+ }
+
+ TimerData& t = timerData[timerIndex];
+ if (!t.used) {
+ t.data = data;
+ t.callback = cb;
+ memset(&t.sigevent, 0, sizeof(struct sigevent));
+ t.sigevent.sigev_notify = SIGEV_THREAD;
+ t.sigevent.sigev_notify_function = timer_signal_handler;
+ t.sigevent.sigev_value.sival_int = timerIndex;
+ ret = timer_create(CLOCK_MONOTONIC, &t.sigevent, &t.handle);
+ if (ret==-1) {
+ Fl_Android_Application::log_e("Can't create timer: %s", strerror(errno));
+ return;
+ }
+ t.used = true;
+ }
+
+ double ff;
+ struct itimerspec timeout = {
+ { 0, 0 },
+ { (time_t)floor(time), (long)(modf(time, &ff)*1000000000) }
+ };
+ ret = timer_settime(t.handle, 0, &timeout, 0L);
+ if (ret==-1) {
+ Fl_Android_Application::log_e("Can't launch timer: %s", strerror(errno));
+ return;
+ }
+ t.triggered = true;
+}
+
+
+int Fl_Android_Screen_Driver::has_timeout(Fl_Timeout_Handler cb, void *data)
+{
+ for (int i = 0; i < nTimerData; ++i) {
+ TimerData& t = timerData[i];
+ if ( (t.used) && (t.callback==cb) && (t.data==data) ) {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+void Fl_Android_Screen_Driver::remove_timeout(Fl_Timeout_Handler cb, void *data)
+{
+ for (int i = 0; i < nTimerData; ++i) {
+ TimerData& t = timerData[i];
+ if ( t.used && (t.callback==cb) && ( (t.data==data) || (data==NULL) ) ) {
+ if (t.used)
+ timer_delete(t.handle);
+ t.triggered = t.used = false;
+ }
+ }
+}
+
+
//
// End of "$Id$".
//