From b34a88065bb1945d08c5cd60dd6243734daecd74 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 12 Mar 2025 09:26:36 +0530 Subject: [PATCH] Wire up clipboard lost events --- glfw/glfw3.h | 3 +++ glfw/init.c | 7 +++++++ glfw/input.c | 5 +++++ glfw/internal.h | 2 ++ glfw/wl_window.c | 2 ++ glfw/x11_window.c | 2 ++ kitty/boss.py | 4 ++++ kitty/glfw-wrapper.c | 3 +++ kitty/glfw-wrapper.h | 6 ++++++ kitty/glfw.c | 6 ++++++ 10 files changed, 40 insertions(+) diff --git a/glfw/glfw3.h b/glfw/glfw3.h index 4e4c85198..4856e1665 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1432,6 +1432,7 @@ typedef void (* GLFWwindowclosefun)(GLFWwindow*); */ typedef void (* GLFWapplicationclosefun)(int); + /*! @brief The function pointer type for system color theme change callbacks. * * This is the function pointer type for system color theme changes. @@ -1814,6 +1815,7 @@ typedef enum { typedef GLFWDataChunk (* GLFWclipboarditerfun)(const char *mime_type, void *iter, GLFWClipboardType ctype); typedef bool (* GLFWclipboardwritedatafun)(void *object, const char *data, size_t sz); typedef bool (* GLFWimecursorpositionfun)(GLFWwindow *window, GLFWIMEUpdateEvent *ev); +typedef void (* GLFWclipboardlostfun )(GLFWClipboardType); /*! @brief Video mode type. * @@ -3985,6 +3987,7 @@ GLFWAPI GLFWwindowsizefun glfwSetWindowSizeCallback(GLFWwindow* window, GLFWwind GLFWAPI GLFWwindowclosefun glfwSetWindowCloseCallback(GLFWwindow* window, GLFWwindowclosefun callback); GLFWAPI GLFWapplicationclosefun glfwSetApplicationCloseCallback(GLFWapplicationclosefun callback); GLFWAPI GLFWsystemcolorthemechangefun glfwSetSystemColorThemeChangeCallback(GLFWsystemcolorthemechangefun callback); +GLFWAPI GLFWclipboardlostfun glfwSetClipboardLostCallback(GLFWclipboardlostfun callback); GLFWAPI GLFWColorScheme glfwGetCurrentSystemColorTheme(bool query_if_unintialized); /*! @brief Sets the refresh callback for the specified window. diff --git a/glfw/init.c b/glfw/init.c index 9315d215a..796cac68b 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -395,6 +395,13 @@ GLFWAPI GLFWsystemcolorthemechangefun glfwSetSystemColorThemeChangeCallback(GLFW return cbfun; } +GLFWAPI GLFWclipboardlostfun glfwSetClipboardLostCallback(GLFWclipboardlostfun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.clipboard_lost, cbfun); + return cbfun; +} + GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun cbfun) { diff --git a/glfw/input.c b/glfw/input.c index 27023b1aa..a7a3cc7d4 100644 --- a/glfw/input.c +++ b/glfw/input.c @@ -453,6 +453,11 @@ void _glfwInputColorScheme(GLFWColorScheme value, bool is_initial_value) { if (_glfw.callbacks.system_color_theme_change) _glfw.callbacks.system_color_theme_change(value, is_initial_value); } +void _glfwInputClipboardLost(GLFWClipboardType which) { + if (_glfw.callbacks.clipboard_lost) _glfw.callbacks.clipboard_lost(which); +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// diff --git a/glfw/internal.h b/glfw/internal.h index da6035c86..f0c4476fb 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -644,6 +644,7 @@ struct _GLFWlibrary GLFWmonitorfun monitor; GLFWjoystickfun joystick; GLFWapplicationclosefun application_close; + GLFWclipboardlostfun clipboard_lost; GLFWsystemcolorthemechangefun system_color_theme_change; GLFWdrawtextfun draw_text; GLFWcurrentselectionfun get_current_selection; @@ -809,6 +810,7 @@ void _glfwInputWindowCloseRequest(_GLFWwindow* window); void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor); void _glfwInputKeyboard(_GLFWwindow *window, GLFWkeyevent *ev); +void _glfwInputClipboardLost(GLFWClipboardType which); void _glfwInputScroll(_GLFWwindow* window, double xoffset, double yoffset, int flags, int mods); void _glfwInputMouseClick(_GLFWwindow* window, int button, int action, int mods); void _glfwInputCursorPos(_GLFWwindow* window, double xpos, double ypos); diff --git a/glfw/wl_window.c b/glfw/wl_window.c index 7fa344265..b56b964b8 100644 --- a/glfw/wl_window.c +++ b/glfw/wl_window.c @@ -2204,6 +2204,7 @@ static void data_source_canceled(void *data UNUSED, struct wl_data_source *wl_da if (_glfw.wl.dataSourceForClipboard == wl_data_source) { _glfw.wl.dataSourceForClipboard = NULL; _glfw_free_clipboard_data(&_glfw.clipboard); + _glfwInputClipboardLost(GLFW_CLIPBOARD); } wl_data_source_destroy(wl_data_source); } @@ -2212,6 +2213,7 @@ static void primary_selection_source_canceled(void *data UNUSED, struct zwp_prim if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source) { _glfw.wl.dataSourceForPrimarySelection = NULL; _glfw_free_clipboard_data(&_glfw.primary); + _glfwInputClipboardLost(GLFW_PRIMARY_SELECTION); } zwp_primary_selection_source_v1_destroy(primary_selection_source); } diff --git a/glfw/x11_window.c b/glfw/x11_window.c index ee11a4627..0683f7446 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -902,10 +902,12 @@ static void handleSelectionClear(XEvent* event) if (event->xselectionclear.selection == _glfw.x11.PRIMARY) { _glfw_free_clipboard_data(&_glfw.primary); + _glfwInputClipboardLost(GLFW_PRIMARY_SELECTION); } else { _glfw_free_clipboard_data(&_glfw.clipboard); + _glfwInputClipboardLost(GLFW_CLIPBOARD); } } diff --git a/kitty/boss.py b/kitty/boss.py index 64e44768b..0994a7ac9 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -18,6 +18,7 @@ from time import sleep from typing import ( TYPE_CHECKING, Any, + Literal, Optional, Union, ) @@ -3109,3 +3110,6 @@ class Boss: cocoa_show_progress_bar_on_dock_icon(101) else: cocoa_show_progress_bar_on_dock_icon() + + def on_clipboard_lost(self, which: Literal['clipboard', 'primary']) -> None: + pass diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index 369e2cf53..ee95c04e9 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -245,6 +245,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetSystemColorThemeChangeCallback_impl) = dlsym(handle, "glfwSetSystemColorThemeChangeCallback"); if (glfwSetSystemColorThemeChangeCallback_impl == NULL) fail("Failed to load glfw function glfwSetSystemColorThemeChangeCallback with error: %s", dlerror()); + *(void **) (&glfwSetClipboardLostCallback_impl) = dlsym(handle, "glfwSetClipboardLostCallback"); + if (glfwSetClipboardLostCallback_impl == NULL) fail("Failed to load glfw function glfwSetClipboardLostCallback with error: %s", dlerror()); + *(void **) (&glfwGetCurrentSystemColorTheme_impl) = dlsym(handle, "glfwGetCurrentSystemColorTheme"); if (glfwGetCurrentSystemColorTheme_impl == NULL) fail("Failed to load glfw function glfwGetCurrentSystemColorTheme with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index c9c23d94f..884663b6f 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1170,6 +1170,7 @@ typedef void (* GLFWwindowclosefun)(GLFWwindow*); */ typedef void (* GLFWapplicationclosefun)(int); + /*! @brief The function pointer type for system color theme change callbacks. * * This is the function pointer type for system color theme changes. @@ -1552,6 +1553,7 @@ typedef enum { typedef GLFWDataChunk (* GLFWclipboarditerfun)(const char *mime_type, void *iter, GLFWClipboardType ctype); typedef bool (* GLFWclipboardwritedatafun)(void *object, const char *data, size_t sz); typedef bool (* GLFWimecursorpositionfun)(GLFWwindow *window, GLFWIMEUpdateEvent *ev); +typedef void (* GLFWclipboardlostfun )(GLFWClipboardType); /*! @brief Video mode type. * @@ -2017,6 +2019,10 @@ typedef GLFWsystemcolorthemechangefun (*glfwSetSystemColorThemeChangeCallback_fu GFW_EXTERN glfwSetSystemColorThemeChangeCallback_func glfwSetSystemColorThemeChangeCallback_impl; #define glfwSetSystemColorThemeChangeCallback glfwSetSystemColorThemeChangeCallback_impl +typedef GLFWclipboardlostfun (*glfwSetClipboardLostCallback_func)(GLFWclipboardlostfun); +GFW_EXTERN glfwSetClipboardLostCallback_func glfwSetClipboardLostCallback_impl; +#define glfwSetClipboardLostCallback glfwSetClipboardLostCallback_impl + typedef GLFWColorScheme (*glfwGetCurrentSystemColorTheme_func)(bool); GFW_EXTERN glfwGetCurrentSystemColorTheme_func glfwGetCurrentSystemColorTheme_impl; #define glfwGetCurrentSystemColorTheme glfwGetCurrentSystemColorTheme_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index 536c85261..7960d0e13 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -65,6 +65,11 @@ on_system_color_scheme_change(GLFWColorScheme appearance, bool is_initial_value) call_boss(on_system_color_scheme_change, "sO", which, is_initial_value ? Py_True : Py_False); } +static void +on_clipboard_lost(GLFWClipboardType which) { + call_boss(on_clipboard_lost, "s", which == GLFW_CLIPBOARD ? "clipboard" : "primary"); +} + static void strip_csi_(const char *title, char *buf, size_t bufsz) { enum { NORMAL, IN_ESC, IN_CSI} state = NORMAL; @@ -1195,6 +1200,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { glfwSetHasCurrentSelectionCallback(has_current_selection); glfwSetIMECursorPositionCallback(get_ime_cursor_position); glfwSetSystemColorThemeChangeCallback(on_system_color_scheme_change); + glfwSetClipboardLostCallback(on_clipboard_lost); // Request SRGB output buffer // Prevents kitty from starting on Wayland + NVIDIA, sigh: https://github.com/kovidgoyal/kitty/issues/7021 // Remove after https://github.com/NVIDIA/egl-wayland/issues/85 is fixed.