diff --git a/glfw/glfw3.h b/glfw/glfw3.h index e8267165d..513c47bc7 100644 --- a/glfw/glfw3.h +++ b/glfw/glfw3.h @@ -1716,6 +1716,7 @@ typedef void (* GLFWjoystickfun)(int,int); typedef void (* GLFWuserdatafun)(unsigned long long, void*); typedef void (* GLFWtickcallback)(void*); typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin); +typedef const char* (* GLFWcurrentselectionfun)(void); /*! @brief Video mode type. * @@ -1873,6 +1874,7 @@ GLFWAPI unsigned long long glfwAddTimer(monotonic_t interval, bool repeats, GLFW GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, monotonic_t interval, bool enabled); GLFWAPI void glfwRemoveTimer(unsigned long long); GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun function); +GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun callback); /*! @brief Terminates the GLFW library. * diff --git a/glfw/init.c b/glfw/init.c index 21bd744c1..13c535635 100644 --- a/glfw/init.c +++ b/glfw/init.c @@ -386,3 +386,10 @@ GLFWAPI GLFWdrawtextfun glfwSetDrawTextFunction(GLFWdrawtextfun cbfun) _GLFW_SWAP_POINTERS(_glfw.callbacks.draw_text, cbfun); return cbfun; } + +GLFWAPI GLFWcurrentselectionfun glfwSetCurrentSelectionCallback(GLFWcurrentselectionfun cbfun) +{ + _GLFW_REQUIRE_INIT_OR_RETURN(NULL); + _GLFW_SWAP_POINTERS(_glfw.callbacks.get_current_selection, cbfun); + return cbfun; +} diff --git a/glfw/internal.h b/glfw/internal.h index a36403457..101921a25 100644 --- a/glfw/internal.h +++ b/glfw/internal.h @@ -621,6 +621,7 @@ struct _GLFWlibrary GLFWjoystickfun joystick; GLFWapplicationclosefun application_close; GLFWdrawtextfun draw_text; + GLFWcurrentselectionfun get_current_selection; } callbacks; diff --git a/kitty/boss.py b/kitty/boss.py index 966df341e..b3eaaf848 100644 --- a/kitty/boss.py +++ b/kitty/boss.py @@ -1614,6 +1614,12 @@ class Boss: if get_options().copy_on_select: self.copy_to_buffer(get_options().copy_on_select) + def get_active_selection(self) -> Optional[str]: + w = self.active_window + if w is not None and not w.destroyed: + return w.text_for_selection() + return None + @ac('cp', ''' Copy the selection from the active window to the specified buffer diff --git a/kitty/glfw-wrapper.c b/kitty/glfw-wrapper.c index e92f1d785..df19f72c2 100644 --- a/kitty/glfw-wrapper.c +++ b/kitty/glfw-wrapper.c @@ -38,6 +38,9 @@ load_glfw(const char* path) { *(void **) (&glfwSetDrawTextFunction_impl) = dlsym(handle, "glfwSetDrawTextFunction"); if (glfwSetDrawTextFunction_impl == NULL) fail("Failed to load glfw function glfwSetDrawTextFunction with error: %s", dlerror()); + *(void **) (&glfwSetCurrentSelectionCallback_impl) = dlsym(handle, "glfwSetCurrentSelectionCallback"); + if (glfwSetCurrentSelectionCallback_impl == NULL) fail("Failed to load glfw function glfwSetCurrentSelectionCallback with error: %s", dlerror()); + *(void **) (&glfwTerminate_impl) = dlsym(handle, "glfwTerminate"); if (glfwTerminate_impl == NULL) fail("Failed to load glfw function glfwTerminate with error: %s", dlerror()); diff --git a/kitty/glfw-wrapper.h b/kitty/glfw-wrapper.h index 36e655edd..152e7d1bf 100644 --- a/kitty/glfw-wrapper.h +++ b/kitty/glfw-wrapper.h @@ -1454,6 +1454,7 @@ typedef void (* GLFWjoystickfun)(int,int); typedef void (* GLFWuserdatafun)(unsigned long long, void*); typedef void (* GLFWtickcallback)(void*); typedef bool (* GLFWdrawtextfun)(GLFWwindow *window, const char *text, uint32_t fg, uint32_t bg, uint8_t *output_buf, size_t width, size_t height, float x_offset, float y_offset, size_t right_margin); +typedef const char* (* GLFWcurrentselectionfun)(void); /*! @brief Video mode type. * @@ -1643,6 +1644,10 @@ typedef GLFWdrawtextfun (*glfwSetDrawTextFunction_func)(GLFWdrawtextfun); GFW_EXTERN glfwSetDrawTextFunction_func glfwSetDrawTextFunction_impl; #define glfwSetDrawTextFunction glfwSetDrawTextFunction_impl +typedef GLFWcurrentselectionfun (*glfwSetCurrentSelectionCallback_func)(GLFWcurrentselectionfun); +GFW_EXTERN glfwSetCurrentSelectionCallback_func glfwSetCurrentSelectionCallback_impl; +#define glfwSetCurrentSelectionCallback glfwSetCurrentSelectionCallback_impl + typedef void (*glfwTerminate_func)(void); GFW_EXTERN glfwTerminate_func glfwTerminate_impl; #define glfwTerminate glfwTerminate_impl diff --git a/kitty/glfw.c b/kitty/glfw.c index cbe543480..d083da7b1 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -464,6 +464,18 @@ application_close_requested_callback(int flags) { } } +const char* +get_current_selection(void) { + if (!global_state.boss) return NULL; + PyObject *ret = PyObject_CallMethod(global_state.boss, "get_active_selection", NULL); + if (!ret) { PyErr_Print(); return NULL; } + const char* ans = NULL; + if (PyUnicode_Check(ret)) ans = strdup(PyUnicode_AsUTF8(ret)); + Py_DECREF(ret); + return ans; +} + + static void get_window_dpi(GLFWwindow *w, double *x, double *y); #ifdef __APPLE__ @@ -764,6 +776,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { glfwWindowHint(GLFW_STENCIL_BITS, 0); if (OPT(hide_window_decorations) & 1) glfwWindowHint(GLFW_DECORATED, false); glfwSetApplicationCloseCallback(application_close_requested_callback); + glfwSetCurrentSelectionCallback(get_current_selection); #ifdef __APPLE__ cocoa_set_activation_policy(OPT(macos_hide_from_tasks)); glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, true);