diff --git a/glfw/x11_window.c b/glfw/x11_window.c index b4daadb77..4e9989e5e 100644 --- a/glfw/x11_window.c +++ b/glfw/x11_window.c @@ -923,27 +923,13 @@ static void handleSelectionRequest(XEvent* event) } static void -getSelectionString(Atom selection, const char *mime_type, Atom *targets, size_t num_targets, GLFWclipboardwritedatafun write_data, void *object, bool report_not_found) +getSelectionString(Atom selection, Atom *targets, size_t num_targets, GLFWclipboardwritedatafun write_data, void *object, bool report_not_found) { #define XFREE(x) { if (x) XFree(x); x = NULL; } - if (XGetSelectionOwner(_glfw.x11.display, selection) == - _glfw.x11.helperWindowHandle) - { - if (mime_type == NULL) { - AtomArray *aa = selection == _glfw.x11.PRIMARY ? &_glfw.x11.primary_atoms : &_glfw.x11.clipboard_atoms; - for (size_t i = 0; i < aa->sz; i++) { - if (!write_data(object, (char*)&aa->array[i].atom, sizeof(Atom))) break; - } - return; - } - // Instead of doing a large number of X round-trips just to put this - // string into a window property and then read it back, just return it - _GLFWClipboardData *cd = selection == _glfw.x11.PRIMARY ? &_glfw.primary : &_glfw.clipboard; - char *data = NULL; size_t sz = get_clipboard_data(cd, mime_type, &data); - write_data(object, data, sz); free(data); + if (XGetSelectionOwner(_glfw.x11.display, selection) == _glfw.x11.helperWindowHandle) { + write_data(object, NULL, 1); return; } - bool found = false; for (size_t i = 0; !found && i < num_targets; i++) { @@ -2928,7 +2914,7 @@ write_chunk(void *object, const char *data, size_t sz) { static void get_available_mime_types(Atom which_clipboard, GLFWclipboardwritedatafun write_data, void *object) { chunked_writer cw = {0}; - getSelectionString(which_clipboard, NULL, &_glfw.x11.TARGETS, 1, write_chunk, &cw, false); + getSelectionString(which_clipboard, &_glfw.x11.TARGETS, 1, write_chunk, &cw, false); size_t count = 0; bool ok = true; if (cw.buf) { @@ -2964,7 +2950,7 @@ _glfwPlatformGetClipboard(GLFWClipboardType clipboard_type, const char* mime_typ atoms[count++] = _glfw.x11.UTF8_STRING; atoms[count++] = XA_STRING; } - getSelectionString(which, mime_type, atoms, count, write_data, object, true); + getSelectionString(which, atoms, count, write_data, object, true); } EGLenum _glfwPlatformGetEGLPlatform(EGLint** attribs) diff --git a/kitty/clipboard.py b/kitty/clipboard.py index b1de2e732..aaa1b6646 100644 --- a/kitty/clipboard.py +++ b/kitty/clipboard.py @@ -35,12 +35,30 @@ class Clipboard: def get_mime(self, mime: str, output: Callable[[bytes], None]) -> None: if self.enabled: - get_clipboard_mime(self.clipboard_type, mime, output) + try: + get_clipboard_mime(self.clipboard_type, mime, output) + except RuntimeError as err: + if str(err) != 'is_self_offer': + raise + data = self.data.get(mime, b'') + if isinstance(data, bytes): + output(data) + else: + data.seek(0, 0) + q = b' ' + while q: + q = data.read(io.DEFAULT_BUFFER_SIZE) + output(q) def get_available_mime_types_for_paste(self) -> Tuple[str, ...]: if self.enabled: parts: List[bytes] = [] - get_clipboard_mime(self.clipboard_type, None, parts.append) + try: + get_clipboard_mime(self.clipboard_type, None, parts.append) + except RuntimeError as err: + if str(err) != 'is_self_offer': + raise + return tuple(self.data) return tuple(x.decode('utf-8', 'replace') for x in uniq(parts)) return () diff --git a/kitty/glfw.c b/kitty/glfw.c index 505769dfe..761adaf4d 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1629,6 +1629,10 @@ set_clipboard_data_types(PyObject *self UNUSED, PyObject *args) { static bool write_clipboard_data(void *callback, const char *data, size_t sz) { Py_ssize_t z = sz; + if (data == NULL) { + PyErr_SetString(PyExc_RuntimeError, "is_self_offer"); + return false; + } PyObject *ret = PyObject_CallFunction(callback, "y#", data, z); bool ok = false; if (ret != NULL) { ok = true; Py_DECREF(ret); }