diff --git a/glfw/cocoa_init.m b/glfw/cocoa_init.m index 1b8dfb325..29e087a13 100644 --- a/glfw/cocoa_init.m +++ b/glfw/cocoa_init.m @@ -424,7 +424,7 @@ display_reconfigured(CGDirectDisplayID display UNUSED, CGDisplayChangeSummaryFla - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { (void)sender; - if (_glfw.ns.quitRequestedCallback) _glfw.ns.quitRequestedCallback(); + if (_glfw.callbacks.application_close) _glfw.callbacks.application_close(0); return NSTerminateCancel; } @@ -585,12 +585,6 @@ GLFWAPI GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunch return previous; } -GLFWAPI GLFWcocoaaplicationquitrequestedfun glfwSetApplicationQuitRequestedCallback(GLFWcocoaaplicationquitrequestedfun callback) { - GLFWcocoaaplicationquitrequestedfun ret = _glfw.ns.quitRequestedCallback; - _glfw.ns.quitRequestedCallback = callback; - return ret; -} - int _glfwPlatformInit(void) { @autoreleasepool { diff --git a/glfw/cocoa_platform.h b/glfw/cocoa_platform.h index 476ac4a41..ed6305170 100644 --- a/glfw/cocoa_platform.h +++ b/glfw/cocoa_platform.h @@ -69,7 +69,6 @@ typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int, unsigned long) typedef bool (* GLFWapplicationshouldhandlereopenfun)(int); typedef void (* GLFWapplicationwillfinishlaunchingfun)(void); typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); -typedef void (* GLFWcocoaaplicationquitrequestedfun)(void); typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); typedef VkFlags VkMacOSSurfaceCreateFlagsMVK; @@ -189,8 +188,6 @@ typedef struct _GLFWlibraryNS double restoreCursorPosX, restoreCursorPosY; // The window whose disabled cursor mode is active _GLFWwindow* disabledCursorWindow; - // The application quit requested callback - GLFWcocoaaplicationquitrequestedfun quitRequestedCallback; struct { CFBundleRef bundle; diff --git a/glfw/glfw.py b/glfw/glfw.py index 1eecdeddd..79954eda7 100755 --- a/glfw/glfw.py +++ b/glfw/glfw.py @@ -203,7 +203,6 @@ def generate_wrappers(glfw_header: str) -> None: GLFWcocoatogglefullscreenfun glfwSetCocoaToggleFullscreenIntercept(GLFWwindow *window, GLFWcocoatogglefullscreenfun callback) GLFWapplicationshouldhandlereopenfun glfwSetApplicationShouldHandleReopen(GLFWapplicationshouldhandlereopenfun callback) GLFWapplicationwillfinishlaunchingfun glfwSetApplicationWillFinishLaunching(GLFWapplicationwillfinishlaunchingfun callback) - GLFWcocoaaplicationquitrequestedfun glfwSetApplicationQuitRequestedCallback(GLFWcocoaaplicationquitrequestedfun callback) void glfwGetCocoaKeyEquivalent(int glfw_key, int glfw_mods, char* cocoa_key, size_t key_sz, int* cocoa_mods) void glfwCocoaRequestRenderFrame(GLFWwindow *w, GLFWcocoarenderframefun callback) void* glfwGetX11Display(void) @@ -244,7 +243,6 @@ typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long); typedef bool (* GLFWapplicationshouldhandlereopenfun)(int); typedef void (* GLFWapplicationwillfinishlaunchingfun)(void); typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); -typedef void (* GLFWcocoaaplicationquitrequestedfun)(void); typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*); diff --git a/glfw/glfw3.h b/glfw/glfw3.h index c231502e9..34f26b543 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1320,6 +1320,22 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); +/*! @brief The function pointer type for application close callbacks. + * + * This is the function pointer type for application close callbacks. A application + * close callback function has the following signature: + * @code + * void function_name(int flags) + * @endcode + * + * @param[in] flags 0 for a user requested application quit, 1 if a fatal error occurred and application should quit ASAP + * + * @sa @ref glfwSetApplicationCloseCallback + * + * @ingroup window + */ +typedef void (* GLFWapplicationclosefun)(int); + /*! @brief The function pointer type for window content refresh callbacks. * * This is the function pointer type for window content refresh callbacks. @@ -3828,6 +3844,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind * @ingroup window */ GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); +GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback); /*! @brief Sets the refresh callback for the specified window. * diff --git a/glfw/init.c b/glfw/init.c index 1df39bc01..dc15fcc96 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -363,3 +363,10 @@ GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, GLFWAPI void glfwRemoveTimer(unsigned long long timer_id) { _glfwPlatformRemoveTimer(timer_id); } + +GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.application_close, cbfun); + return cbfun; +} diff --git a/glfw/internal.h b/glfw/internal.h index e48651db1..98d08fad1 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -602,8 +602,10 @@ struct _GLFWlibrary struct { GLFWmonitorfun monitor; GLFWjoystickfun joystick; + GLFWapplicationclosefun application_close; } callbacks; + // This is defined in the window API's platform.h _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; // This is defined in the context API's context.h diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 9513d119f..001b4c7c3 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -760,11 +760,14 @@ animateCursorImage(id_type timer_id UNUSED, void *data UNUSED) { static void abortOnFatalError(int last_error) { _glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: fatal display error: %s", strerror(last_error)); - _GLFWwindow* window = _glfw.windowListHead; - while (window) - { - _glfwInputWindowCloseRequest(window); - window = window->next; + if (_glfw.callbacks.application_close) _glfw.callbacks.application_close(1); + else { + _GLFWwindow* window = _glfw.windowListHead; + while (window) + { + _glfwInputWindowCloseRequest(window); + window = window->next; + } } // ensure the tick callback is called _glfw.wl.eventLoopData.wakeup_data_read = true; diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index e0e3eb848..c5629e5d0 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -216,6 +216,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetWindowCloseCallback_impl) = dlsym(handle, "glfwSetWindowCloseCallback"); if (glfwSetWindowCloseCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowCloseCallback with error: %s", dlerror()); + *(void **) (&glfwSetApplicationCloseCallback_impl) = dlsym(handle, "glfwSetApplicationCloseCallback"); + if (glfwSetApplicationCloseCallback_impl == NULL) fail("Failed to load glfw function glfwSetApplicationCloseCallback with error: %s", dlerror()); + *(void **) (&glfwSetWindowRefreshCallback_impl) = dlsym(handle, "glfwSetWindowRefreshCallback"); if (glfwSetWindowRefreshCallback_impl == NULL) fail("Failed to load glfw function glfwSetWindowRefreshCallback with error: %s", dlerror()); @@ -246,6 +249,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetInputMode_impl) = dlsym(handle, "glfwSetInputMode"); if (glfwSetInputMode_impl == NULL) fail("Failed to load glfw function glfwSetInputMode with error: %s", dlerror()); + *(void **) (&glfwRawMouseMotionSupported_impl) = dlsym(handle, "glfwRawMouseMotionSupported"); + if (glfwRawMouseMotionSupported_impl == NULL) fail("Failed to load glfw function glfwRawMouseMotionSupported with error: %s", dlerror()); + *(void **) (&glfwGetKeyName_impl) = dlsym(handle, "glfwGetKeyName"); if (glfwGetKeyName_impl == NULL) fail("Failed to load glfw function glfwGetKeyName with error: %s", dlerror()); @@ -386,8 +392,6 @@ load_glfw(const char* path) { *(void **) (&glfwSetApplicationWillFinishLaunching_impl) = dlsym(handle, "glfwSetApplicationWillFinishLaunching"); - *(void **) (&glfwSetApplicationQuitRequestedCallback_impl) = dlsym(handle, "glfwSetApplicationQuitRequestedCallback"); - *(void **) (&glfwGetCocoaKeyEquivalent_impl) = dlsym(handle, "glfwGetCocoaKeyEquivalent"); *(void **) (&glfwCocoaRequestRenderFrame_impl) = dlsym(handle, "glfwCocoaRequestRenderFrame"); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 84865eb41..e1a93c78d 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1083,6 +1083,22 @@ typedef void (* GLFWwindowsizefun)(GLFWwindow*,int,int); */ typedef void (* GLFWwindowclosefun)(GLFWwindow*); +/*! @brief The function pointer type for application close callbacks. + * + * This is the function pointer type for application close callbacks. A application + * close callback function has the following signature: + * @code + * void function_name(int flags) + * @endcode + * + * @param[in] flags 0 for a user requested application quit, 1 if a fatal error occurred and application should quit ASAP + * + * @sa @ref glfwSetApplicationCloseCallback + * + * @ingroup window + */ +typedef void (* GLFWapplicationclosefun)(int); + /*! @brief The function pointer type for window content refresh callbacks. * * This is the function pointer type for window content refresh callbacks. @@ -1587,7 +1603,6 @@ typedef int (* GLFWcocoatextinputfilterfun)(int,int,unsigned int,unsigned long); typedef bool (* GLFWapplicationshouldhandlereopenfun)(int); typedef void (* GLFWapplicationwillfinishlaunchingfun)(void); typedef bool (* GLFWcocoatogglefullscreenfun)(GLFWwindow*); -typedef void (* GLFWcocoaaplicationquitrequestedfun)(void); typedef void (* GLFWcocoarenderframefun)(GLFWwindow*); typedef void (*GLFWwaylandframecallbackfunc)(unsigned long long id); typedef void (*GLFWDBusnotificationcreatedfun)(unsigned long long, uint32_t, void*); @@ -1860,6 +1875,10 @@ typedef GLFWwindowclosefun (*glfwSetWindowCloseCallback_func)(GLFWwindow*, GLFWw GFW_EXTERN glfwSetWindowCloseCallback_func glfwSetWindowCloseCallback_impl; #define glfwSetWindowCloseCallback glfwSetWindowCloseCallback_impl +typedef GLFWapplicationclosefun (*glfwSetApplicationCloseCallback_func)(GLFWapplicationclosefun); +GFW_EXTERN glfwSetApplicationCloseCallback_func glfwSetApplicationCloseCallback_impl; +#define glfwSetApplicationCloseCallback glfwSetApplicationCloseCallback_impl + typedef GLFWwindowrefreshfun (*glfwSetWindowRefreshCallback_func)(GLFWwindow*, GLFWwindowrefreshfun); GFW_EXTERN glfwSetWindowRefreshCallback_func glfwSetWindowRefreshCallback_impl; #define glfwSetWindowRefreshCallback glfwSetWindowRefreshCallback_impl @@ -1900,6 +1919,10 @@ typedef void (*glfwSetInputMode_func)(GLFWwindow*, int, int); GFW_EXTERN glfwSetInputMode_func glfwSetInputMode_impl; #define glfwSetInputMode glfwSetInputMode_impl +typedef int (*glfwRawMouseMotionSupported_func)(void); +GFW_EXTERN glfwRawMouseMotionSupported_func glfwRawMouseMotionSupported_impl; +#define glfwRawMouseMotionSupported glfwRawMouseMotionSupported_impl + typedef const char* (*glfwGetKeyName_func)(int, int); GFW_EXTERN glfwGetKeyName_func glfwGetKeyName_impl; #define glfwGetKeyName glfwGetKeyName_impl @@ -2096,10 +2119,6 @@ typedef GLFWapplicationwillfinishlaunchingfun (*glfwSetApplicationWillFinishLaun GFW_EXTERN glfwSetApplicationWillFinishLaunching_func glfwSetApplicationWillFinishLaunching_impl; #define glfwSetApplicationWillFinishLaunching glfwSetApplicationWillFinishLaunching_impl -typedef GLFWcocoaaplicationquitrequestedfun (*glfwSetApplicationQuitRequestedCallback_func)(GLFWcocoaaplicationquitrequestedfun); -GFW_EXTERN glfwSetApplicationQuitRequestedCallback_func glfwSetApplicationQuitRequestedCallback_impl; -#define glfwSetApplicationQuitRequestedCallback glfwSetApplicationQuitRequestedCallback_impl - typedef void (*glfwGetCocoaKeyEquivalent_func)(int, int, char*, size_t, int*); GFW_EXTERN glfwGetCocoaKeyEquivalent_func glfwGetCocoaKeyEquivalent_impl; #define glfwGetCocoaKeyEquivalent glfwGetCocoaKeyEquivalent_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index b73f0da04..87d605d6f 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -332,16 +332,19 @@ drop_callback(GLFWwindow *w, const char *mime, const char *data, size_t sz) { #undef RETURN } -#ifdef __APPLE__ static void -application_quit_requested_callback(void) { - if (global_state.quit_request == NO_CLOSE_REQUESTED) { - global_state.has_pending_closes = true; - global_state.quit_request = CONFIRMABLE_CLOSE_REQUESTED; +application_close_requested_callback(int flags) { + if (flags) { + global_state.quit_request = IMPERATIVE_CLOSE_REQUESTED; request_tick_callback(); + } else { + if (global_state.quit_request == NO_CLOSE_REQUESTED) { + global_state.has_pending_closes = true; + global_state.quit_request = CONFIRMABLE_CLOSE_REQUESTED; + request_tick_callback(); + } } } -#endif // }}} void @@ -523,12 +526,12 @@ create_os_window(PyObject UNUSED *self, PyObject *args) { glfwWindowHint(GLFW_DEPTH_BITS, 0); glfwWindowHint(GLFW_STENCIL_BITS, 0); if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false); + glfwSetApplicationCloseCallback(application_close_requested_callback); #ifdef __APPLE__ cocoa_set_activation_policy(OPT(macos_hide_from_tasks)); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, true); glfwSetApplicationShouldHandleReopen(on_application_reopen); glfwSetApplicationWillFinishLaunching(cocoa_create_global_menu); - glfwSetApplicationQuitRequestedCallback(application_quit_requested_callback); #endif }