From d593ccba2f7fd176649a79990489a403bd512f2b Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 26 Feb 2019 10:29:46 +0530 Subject: [PATCH] Add a loop tick callback --- glfw/glfw3.h | 4 +++- glfw/init.c | 13 ++++++++++--- glfw/internal.h | 3 ++- glfw/x11_init.c | 13 +++++++++++-- kitty/glfw-wrapper.c | 3 +++ kitty/glfw-wrapper.h | 7 ++++++- kitty/glfw.c | 15 +++++++++++++++ kitty/state.h | 4 ++++ 8 files changed, 54 insertions(+), 8 deletions(-) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 1ee5394b5..96b2c8a41 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1510,6 +1510,7 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); typedef void (* GLFWjoystickfun)(int,int); typedef void (* GLFWuserdatafun)(unsigned long long, void*); +typedef void (* GLFWtickcallback)(void*); /*! @brief Video mode type. * @@ -1657,8 +1658,9 @@ typedef struct GLFWgamepadstate * @ingroup init */ GLFWAPI int glfwInit(void); -GLFWAPI void glfwRunMainLoop(void); +GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data); GLFWAPI void glfwStopMainLoop(void); +GLFWAPI void glfwRequestTickCallback(void); GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback); GLFWAPI void glfwRemoveTimer(unsigned long long); diff --git a/glfw/init.c b/glfw/init.c index 3f554c6cd..6e9fe4db2 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -322,10 +322,14 @@ GLFWAPI GLFWerrorfun glfwSetErrorCallback(GLFWerrorfun cbfun) } -GLFWAPI void glfwRunMainLoop(void) +GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *data) { _GLFW_REQUIRE_INIT(); - _glfwPlatformRunMainLoop(); + _glfwPlatformRunMainLoop(callback, data); +} + +GLFWAPI void glfwRequestTickCallback(void) { + _glfwPlatformRequestTickCallback(); } GLFWAPI void glfwStopMainLoop(void) { @@ -333,7 +337,10 @@ GLFWAPI void glfwStopMainLoop(void) { _glfwPlatformStopMainLoop(); } -GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback) { +GLFWAPI unsigned long long glfwAddTimer( + double interval, bool repeats, GLFWuserdatafun callback, + void *callback_data, GLFWuserdatafun free_callback) +{ return _glfwPlatformAddTimer(interval, repeats, callback, callback_data, free_callback); } diff --git a/glfw/internal.h b/glfw/internal.h index 333f52643..e09e29959 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -783,7 +783,8 @@ void _glfwTerminateVulkan(void); const char* _glfwGetVulkanResultString(VkResult result); _GLFWwindow* _glfwFocusedWindow(); _GLFWwindow* _glfwWindowForId(GLFWid id); -void _glfwPlatformRunMainLoop(void); +void _glfwPlatformRunMainLoop(GLFWtickcallback, void*); +void _glfwPlatformRequestTickCallback(); void _glfwPlatformStopMainLoop(void); unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback); void _glfwPlatformRemoveTimer(unsigned long long timer_id); diff --git a/glfw/x11_init.c b/glfw/x11_init.c index c793176c0..399dceec2 100644 --- a/glfw/x11_init.c +++ b/glfw/x11_init.c @@ -770,7 +770,11 @@ const char* _glfwPlatformGetVersionString(void) ; } -static GLFWbool keep_going; +static GLFWbool keep_going = GLFW_FALSE, tick_callback_requested = GLFW_FALSE; + +void _glfwPlatformRequestTickCallback() { + tick_callback_requested = GLFW_TRUE; +} void _glfwPlatformStopMainLoop(void) { if (keep_going) { @@ -779,9 +783,14 @@ void _glfwPlatformStopMainLoop(void) { } } -void _glfwPlatformRunMainLoop(void) { +void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) { keep_going = GLFW_TRUE; + tick_callback_requested = GLFW_FALSE; while(keep_going) { + if (tick_callback_requested) { + tick_callback_requested = GLFW_FALSE; + callback(data); + } _glfwPlatformWaitEvents(); } } diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 733d734a9..08d2b76b8 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -23,6 +23,9 @@ load_glfw(const char* path) { *(void **) (&glfwStopMainLoop_impl) = dlsym(handle, "glfwStopMainLoop"); if (glfwStopMainLoop_impl == NULL) fail("Failed to load glfw function glfwStopMainLoop with error: %s", dlerror()); + *(void **) (&glfwRequestTickCallback_impl) = dlsym(handle, "glfwRequestTickCallback"); + if (glfwRequestTickCallback_impl == NULL) fail("Failed to load glfw function glfwRequestTickCallback with error: %s", dlerror()); + *(void **) (&glfwAddTimer_impl) = dlsym(handle, "glfwAddTimer"); if (glfwAddTimer_impl == NULL) fail("Failed to load glfw function glfwAddTimer with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 5d808264b..f060b3ecc 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1267,6 +1267,7 @@ typedef void (* GLFWmonitorfun)(GLFWmonitor*,int); typedef void (* GLFWjoystickfun)(int,int); typedef void (* GLFWuserdatafun)(unsigned long long, void*); +typedef void (* GLFWtickcallback)(void*); /*! @brief Video mode type. * @@ -1426,7 +1427,7 @@ typedef int (*glfwInit_func)(); glfwInit_func glfwInit_impl; #define glfwInit glfwInit_impl -typedef void (*glfwRunMainLoop_func)(); +typedef void (*glfwRunMainLoop_func)(GLFWtickcallback, void*); glfwRunMainLoop_func glfwRunMainLoop_impl; #define glfwRunMainLoop glfwRunMainLoop_impl @@ -1434,6 +1435,10 @@ typedef void (*glfwStopMainLoop_func)(); glfwStopMainLoop_func glfwStopMainLoop_impl; #define glfwStopMainLoop glfwStopMainLoop_impl +typedef void (*glfwRequestTickCallback_func)(); +glfwRequestTickCallback_func glfwRequestTickCallback_impl; +#define glfwRequestTickCallback glfwRequestTickCallback_impl + typedef unsigned long long (*glfwAddTimer_func)(double, bool, GLFWuserdatafun, void *, GLFWuserdatafun); glfwAddTimer_func glfwAddTimer_impl; #define glfwAddTimer glfwAddTimer_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 1dda8a455..9de6882ca 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1123,6 +1123,21 @@ remove_main_loop_timer(id_type timer_id) { glfwRemoveTimer(timer_id); } +void +run_main_loop(tick_callback_fun cb, void* cb_data) { + glfwRunMainLoop(cb, cb_data); +} + +void +request_tick_callback(void) { + glfwRequestTickCallback(); +} + +void +stop_main_loop(void) { + glfwStopMainLoop(); +} + // Boilerplate {{{ static PyMethodDef module_methods[] = { diff --git a/kitty/state.h b/kitty/state.h index 488a37f71..ac0be71b2 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -222,5 +222,9 @@ void request_application_quit(); #endif void request_frame_render(OSWindow *w); typedef void (* timer_callback_fun)(id_type, void*); +typedef void (* tick_callback_fun)(void*); id_type add_main_loop_timer(double interval, bool repeats, timer_callback_fun callback, void *callback_data, timer_callback_fun free_callback); void remove_main_loop_timer(id_type timer_id); +void run_main_loop(tick_callback_fun, void*); +void request_tick_callback(void); +void stop_main_loop(void);