diff --git a/gral.h b/gral.h index b904ce8..3b4d4d2 100644 --- a/gral.h +++ b/gral.h @@ -157,11 +157,12 @@ void gral_window_show_open_file_dialog(struct gral_window *window, void (*callba void gral_window_show_save_file_dialog(struct gral_window *window, void (*callback)(char const *file, void *user_data), void *user_data); void gral_window_clipboard_copy(struct gral_window *window, char const *text); void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(char const *text, void *user_data), void *user_data); -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); +void gral_run_on_main_thread(void (*callback)(void *user_data), void *user_data); + /*========= FILE diff --git a/gral_linux.c b/gral_linux.c index f192cc0..e35c5fc 100644 --- a/gral_linux.c +++ b/gral_linux.c @@ -638,25 +638,6 @@ 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; -} IdleCallbackData; -static gboolean idle_callback(gpointer user_data) { - IdleCallbackData *callback_data = user_data; - callback_data->callback(callback_data->user_data); - return G_SOURCE_REMOVE; -} -static void idle_destroy(gpointer user_data) { - g_slice_free(IdleCallbackData, user_data); -} -void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) { - IdleCallbackData *callback_data = g_slice_new(IdleCallbackData); - callback_data->callback = callback; - callback_data->user_data = user_data; - 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; @@ -682,6 +663,25 @@ void gral_timer_delete(struct gral_timer *timer) { g_source_remove((guint)(intptr_t)timer); } +typedef struct { + void (*callback)(void *user_data); + void *user_data; +} IdleCallbackData; +static gboolean idle_callback(gpointer user_data) { + IdleCallbackData *callback_data = user_data; + callback_data->callback(callback_data->user_data); + return G_SOURCE_REMOVE; +} +static void idle_destroy(gpointer user_data) { + g_slice_free(IdleCallbackData, user_data); +} +void gral_run_on_main_thread(void (*callback)(void *user_data), void *user_data) { + IdleCallbackData *callback_data = g_slice_new(IdleCallbackData); + callback_data->callback = callback; + callback_data->user_data = user_data; + gdk_threads_add_idle_full(G_PRIORITY_DEFAULT_IDLE, idle_callback, callback_data, idle_destroy); +} + /*========= FILE diff --git a/gral_macos.m b/gral_macos.m index 9d47530..bc0d5ec 100644 --- a/gral_macos.m +++ b/gral_macos.m @@ -667,48 +667,48 @@ void gral_window_clipboard_paste(struct gral_window *window, void (*callback)(ch } } -@interface MainThreadCallbackObject: NSObject { +@interface TimerCallbackObject: NSObject { @public void (*callback)(void *user_data); void *user_data; } @end -@implementation MainThreadCallbackObject -- (void)invoke:(id)object { +@implementation TimerCallbackObject +- (void)invoke:(NSTimer *)timer { callback(user_data); } @end -void gral_window_run_on_main_thread(struct gral_window *window, void (*callback)(void *user_data), void *user_data) { - MainThreadCallbackObject *callback_object = [[MainThreadCallbackObject alloc] init]; + +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; - [callback_object performSelectorOnMainThread:@selector(invoke:) withObject:nil waitUntilDone:NO]; + 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; } -@interface TimerCallbackObject: NSObject { +void gral_timer_delete(struct gral_timer *timer) { + [(NSTimer *)timer invalidate]; +} + +@interface MainThreadCallbackObject: NSObject { @public void (*callback)(void *user_data); void *user_data; } @end -@implementation TimerCallbackObject -- (void)invoke:(NSTimer *)timer { +@implementation MainThreadCallbackObject +- (void)invoke:(id)object { callback(user_data); } @end - -struct gral_timer *gral_timer_create(int milliseconds, void (*callback)(void *user_data), void *user_data) { - TimerCallbackObject *callback_object = [[TimerCallbackObject alloc] init]; +void gral_run_on_main_thread(void (*callback)(void *user_data), void *user_data) { + MainThreadCallbackObject *callback_object = [[MainThreadCallbackObject 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 performSelectorOnMainThread:@selector(invoke:) withObject:nil waitUntilDone:NO]; [callback_object release]; - return (struct gral_timer *)timer; -} - -void gral_timer_delete(struct gral_timer *timer) { - [(NSTimer *)timer invalidate]; } diff --git a/gral_windows.cpp b/gral_windows.cpp index d1531bf..1c83f48 100644 --- a/gral_windows.cpp +++ b/gral_windows.cpp @@ -152,6 +152,7 @@ static ID2D1Factory *factory; static ID2D1StrokeStyle *stroke_style; static IWICImagingFactory *imaging_factory; static IDWriteFactory *dwrite_factory; +static DWORD main_thread_id; struct gral_draw_context { ID2D1HwndRenderTarget *target; @@ -534,6 +535,7 @@ void gral_application_delete(gral_application *application) { } int gral_application_run(gral_application *application, int argc_, char **argv_) { + main_thread_id = GetCurrentThreadId(); int argc; LPWSTR *argv = CommandLineToArgvW(GetCommandLine(), &argc); if (argc > 1) { @@ -1052,27 +1054,6 @@ void gral_window_clipboard_paste(gral_window *window, void (*callback)(char cons CloseClipboard(); } -struct MainThreadCallbackData { - void (*callback)(void *user_data); - void *user_data; -}; - -static void CALLBACK main_thread_completion_routine(ULONG_PTR parameter) { - MainThreadCallbackData *callback_data = (MainThreadCallbackData *)parameter; - callback_data->callback(callback_data->user_data); - delete callback_data; -} - -void gral_window_run_on_main_thread(gral_window *window, void (*callback)(void *user_data), void *user_data) { - MainThreadCallbackData *callback_data = new MainThreadCallbackData(); - callback_data->callback = callback; - callback_data->user_data = user_data; - DWORD thread_id = GetWindowThreadProcessId((HWND)window, NULL); - HANDLE thread = OpenThread(THREAD_SET_CONTEXT, FALSE, thread_id); - QueueUserAPC(&main_thread_completion_routine, thread, (ULONG_PTR)callback_data); - CloseHandle(thread); -} - static void CALLBACK timer_completion_routine(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue, DWORD dwTimerHighValue) { gral_timer *timer = (gral_timer *)lpArgToCompletionRoutine; timer->callback(timer->user_data); @@ -1095,6 +1076,26 @@ void gral_timer_delete(gral_timer *timer) { delete timer; } +struct MainThreadCallbackData { + void (*callback)(void *user_data); + void *user_data; +}; + +static void CALLBACK main_thread_completion_routine(ULONG_PTR parameter) { + MainThreadCallbackData *callback_data = (MainThreadCallbackData *)parameter; + callback_data->callback(callback_data->user_data); + delete callback_data; +} + +void gral_run_on_main_thread(void (*callback)(void *user_data), void *user_data) { + MainThreadCallbackData *callback_data = new MainThreadCallbackData(); + callback_data->callback = callback; + callback_data->user_data = user_data; + HANDLE thread = OpenThread(THREAD_SET_CONTEXT, FALSE, main_thread_id); + QueueUserAPC(&main_thread_completion_routine, thread, (ULONG_PTR)callback_data); + CloseHandle(thread); +} + /*========= FILE