diff --git a/demos/events.c b/demos/events.c index 145c041..99415ec 100644 --- a/demos/events.c +++ b/demos/events.c @@ -40,7 +40,7 @@ static void mouse_button_press(float x, float y, int button, int modifiers, void printf("mouse button press: {%f, %f} (modifiers: %X)\n", x, y, modifiers); struct demo *demo = user_data; if (demo->timer) { - gral_window_delete_timer(demo->window, demo->timer); + gral_timer_delete(demo->timer); demo->timer = 0; } } @@ -126,7 +126,7 @@ static void create_window(void *user_data) { &focus_leave }; demo->window = gral_window_create(demo->application, 600, 400, "gral events demo", &interface, demo); - demo->timer = gral_window_create_timer(demo->window, 1000, &timer, demo); + demo->timer = gral_timer_create(1000, &timer, demo); } static void open_empty(void *user_data) { diff --git a/gral.h b/gral.h index f440589..06dc24a 100644 --- a/gral.h +++ b/gral.h @@ -161,6 +161,9 @@ struct gral_timer *gral_window_create_timer(struct gral_window *window, int mill void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer); void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data); +struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data); +void gral_timer_delete(struct gral_timer *timer); + /*========= FILE diff --git a/gral_linux.c b/gral_linux.c index da9881a..57372b5 100644 --- a/gral_linux.c +++ b/gral_linux.c @@ -638,29 +638,12 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch gtk_clipboard_request_text(clipboard, paste_callback, callback_data); } -typedef struct { - void (*callback)(void *user_data); - void *user_data; -} TimerCallbackData; -static gboolean timer_callback(gpointer user_data) { - TimerCallbackData *callback_data = user_data; - callback_data->callback(callback_data->user_data); - return G_SOURCE_CONTINUE; -} -static void timer_destroy(gpointer user_data) { - TimerCallbackData *callback_data = user_data; - g_slice_free(TimerCallbackData, callback_data); -} - struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) { - TimerCallbackData *callback_data = g_slice_new(TimerCallbackData); - callback_data->callback = callback; - callback_data->user_data = user_data; - return (struct gral_timer *)(intptr_t)g_timeout_add_full(G_PRIORITY_DEFAULT, milliseconds, timer_callback, callback_data, timer_destroy); + return gral_timer_create(milliseconds, callback, user_data); } void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer) { - g_source_remove((guint)(intptr_t)timer); + gral_timer_delete(timer); } typedef struct { @@ -682,6 +665,31 @@ void gral_window_run_on_main_thread(struct gral_window *window, void (*callback) gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, idle_callback, callback_data, idle_destroy); } +typedef struct { + void (*callback)(void *user_data); + void *user_data; +} TimerCallbackData; +static gboolean timer_callback(gpointer user_data) { + TimerCallbackData *callback_data = user_data; + callback_data->callback(callback_data->user_data); + return G_SOURCE_CONTINUE; +} +static void timer_destroy(gpointer user_data) { + TimerCallbackData *callback_data = user_data; + g_slice_free(TimerCallbackData, callback_data); +} + +struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) { + TimerCallbackData *callback_data = g_slice_new(TimerCallbackData); + callback_data->callback = callback; + callback_data->user_data = user_data; + return (struct gral_timer *)(intptr_t)g_timeout_add_full(G_PRIORITY_DEFAULT, milliseconds, timer_callback, callback_data, timer_destroy); +} + +void gral_timer_delete(struct gral_timer *timer) { + g_source_remove((guint)(intptr_t)timer); +} + /*========= FILE diff --git a/gral_macos.m b/gral_macos.m index ab4221f..ee0f37b 100644 --- a/gral_macos.m +++ b/gral_macos.m @@ -679,16 +679,11 @@ - (void)invoke:(NSTimer *)timer { } @end struct gral_timer *gral_window_create_timer(struct gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) { - TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init]; - callback_object->callback = callback; - callback_object->user_data = user_data; - NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0 target:callback_object selector:@selector(invoke:) userInfo:nil repeats:YES]; - [callback_object release]; - return (struct gral_timer *)timer; + return gral_timer_create(milliseconds, callback, user_data); } void gral_window_delete_timer(struct gral_window *window, struct gral_timer *timer) { - [(NSTimer *)timer invalidate]; + gral_timer_delete(timer); } @interface MainThreadCallbackObject: NSObject { @@ -710,6 +705,19 @@ void gral_window_run_on_main_thread(struct gral_window *window, void (*callback) [callback_object release]; } +struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) { + TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init]; + callback_object->callback = callback; + callback_object->user_data = user_data; + NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:milliseconds/1000.0 target:callback_object selector:@selector(invoke:) userInfo:nil repeats:YES]; + [callback_object release]; + return (struct gral_timer *)timer; +} + +void gral_timer_delete(struct gral_timer *timer) { + [(NSTimer *)timer invalidate]; +} + /*========= FILE diff --git a/gral_windows.cpp b/gral_windows.cpp index d0e4c9e..0c0cef9 100644 --- a/gral_windows.cpp +++ b/gral_windows.cpp @@ -203,6 +203,7 @@ struct WindowData { struct gral_timer { void (*callback)(void *user_data); void *user_data; + HANDLE timer; }; @@ -458,12 +459,6 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { case WM_KILLFOCUS: window_data->iface.focus_leave(window_data->user_data); return 0; - case WM_TIMER: - { - gral_timer *timer = (gral_timer *)wParam; - timer->callback(timer->user_data); - return 0; - } case WM_SIZE: { WORD width = LOWORD(lParam); @@ -1065,22 +1060,39 @@ void gral_window_clipboard_paste(gral_window *window, void (*callback)(char cons } gral_timer *gral_window_create_timer(gral_window *window, int milliseconds, void (*callback)(void *user_data), void *user_data) { - gral_timer *timer = new gral_timer(); - timer->callback = callback; - timer->user_data = user_data; - SetTimer((HWND)window, (UINT_PTR)timer, milliseconds, NULL); - return timer; + return gral_timer_create(milliseconds, callback, user_data); } void gral_window_delete_timer(gral_window *window, gral_timer *timer) { - KillTimer((HWND)window, (UINT_PTR)timer); - delete timer; + gral_timer_delete(timer); } void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) { PostMessage((HWND)window, WM_USER, (WPARAM)callback, (LPARAM)user_data); } +static void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) { + gral_timer *timer = (gral_timer *)lpArgToCompletionRoutine; + timer->callback(timer->user_data); +} + +gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) { + gral_timer *timer = new gral_timer(); + timer->callback = callback; + timer->user_data = user_data; + timer->timer = CreateWaitableTimer(NULL, FALSE, NULL); + LARGE_INTEGER due_time; + due_time.QuadPart = (LONGLONG)milliseconds * -10000; + SetWaitableTimer(timer->timer, &due_time, milliseconds, &timer_completion_routine, timer, FALSE); + return timer; +} + +void gral_timer_delete(gral_timer *timer) { + CancelWaitableTimer(timer->timer); + CloseHandle(timer->timer); + delete timer; +} + /*========= FILE @@ -1206,7 +1218,7 @@ struct gral_directory_watcher { } void watch() { const DWORD notify_filter = FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_SECURITY; - ReadDirectoryChangesW(directory, buffer, sizeof(buffer), FALSE, notify_filter, NULL, &overlapped, completion_routine); + ReadDirectoryChangesW(directory, buffer, sizeof(buffer), FALSE, notify_filter, NULL, &overlapped, &completion_routine); } void cancel() { CancelIoEx(directory, &overlapped);