From 7f3c808e6688b6ebad5c5ef00f4d1ad96dd03af0 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 17 Oct 2017 21:44:56 +0530 Subject: [PATCH] Use glfw 3.3 functions for the primary selection Allows us to drop the dependency on xsel for systems with glfw 3.3 --- README.asciidoc | 3 ++- kitty/data-types.c | 2 ++ kitty/utils.py | 24 ++++++++++++++--------- kitty/x11.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 kitty/x11.c diff --git a/README.asciidoc b/README.asciidoc index 7250ca7c8..e5824776c 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -85,7 +85,8 @@ the following dependencies are installed first. * libpng * glew >= 2.0 (not needed on macOS) * fontconfig (not needed on macOS) -* xrdb and xsel (only on X11 based systems) +* xrdb (only on X11 based systems) +* xsel (only on X11 systems with glfw < 3.3) * ImageMagick (optional, needed to use the `kitty icat` tool to display images in the terminal) * gcc or clang (required only for building) * pkg-config (required only for building) diff --git a/kitty/data-types.c b/kitty/data-types.c index 2bc538c09..ccc945d26 100644 --- a/kitty/data-types.c +++ b/kitty/data-types.c @@ -139,6 +139,7 @@ extern bool init_keys(PyObject *module); extern bool init_graphics(PyObject *module); extern bool init_shaders(PyObject *module); extern bool init_shaders_debug(PyObject *module); +extern bool init_x11_funcs(PyObject *module); #ifdef __APPLE__ extern int init_CoreText(PyObject *); extern bool init_cocoa(PyObject *module); @@ -180,6 +181,7 @@ PyInit_fast_data_types(void) { if (!init_Face(m)) return NULL; if (!init_freetype_library(m)) return NULL; if (!init_fontconfig_library(m)) return NULL; + if (!init_x11_funcs(m)) return NULL; #endif #define OOF(n) #n, offsetof(Cell, n) diff --git a/kitty/utils.py b/kitty/utils.py index e9cfa6385..c46e4f61c 100644 --- a/kitty/utils.py +++ b/kitty/utils.py @@ -163,12 +163,14 @@ def parse_color_set(raw): def get_primary_selection(): if isosx: return '' # There is no primary selection on OS X - # glfw has no way to get the primary selection - # https://github.com/glfw/glfw/issues/894 - ans = subprocess.check_output(['xsel', '-p'], stderr=open(os.devnull, 'wb'), stdin=open(os.devnull, 'rb')).decode('utf-8') - if ans: - # Without this for some reason repeated pastes dont work - set_primary_selection(ans) + try: + from .fast_data_types import get_selection_x11 + ans = (get_selection_x11() or b'').decode('utf-8', 'replace') + except ImportError: + ans = subprocess.check_output(['xsel', '-p'], stderr=open(os.devnull, 'wb'), stdin=open(os.devnull, 'rb')).decode('utf-8') + if ans: + # Without this for some reason repeated pastes dont work + set_primary_selection(ans) return ans @@ -191,9 +193,13 @@ def set_primary_selection(text): return # There is no primary selection on OS X if isinstance(text, str): text = text.encode('utf-8') - p = subprocess.Popen(['xsel', '-i', '-p'], stdin=subprocess.PIPE, stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT) - p.stdin.write(text), p.stdin.close() - p.wait() + try: + from .fast_data_types import set_selection_x11 + set_selection_x11(text) + except ImportError: + p = subprocess.Popen(['xsel', '-i', '-p'], stdin=subprocess.PIPE, stdout=open(os.devnull, 'wb'), stderr=subprocess.STDOUT) + p.stdin.write(text), p.stdin.close() + p.wait() def open_url(url, program='default'): diff --git a/kitty/x11.c b/kitty/x11.c new file mode 100644 index 000000000..91cd7f47a --- /dev/null +++ b/kitty/x11.c @@ -0,0 +1,49 @@ +/* + * x11.c + * Copyright (C) 2017 Kovid Goyal + * + * Distributed under terms of the GPL3 license. + */ + +#include +#include +#include +#if GLFW_VERSION_MAJOR > 3 || (GLFW_VERSION_MAJOR == 3 && GLFW_VERSION_MINOR > 2) +#define HAS_X11_SELECTION +#endif + +#ifdef HAS_X11_SELECTION +#define GLFW_EXPOSE_NATIVE_X11 +#include + +static PyObject* +get_selection_x11(PyObject *self) { + (void)(self); + return Py_BuildValue("y", glfwGetX11SelectionString()); +} + +static PyObject* +set_selection_x11(PyObject *self, PyObject *args) { + (void)(self); + const char *data; + if (!PyArg_ParseTuple(args, "y", &data)) return NULL; + glfwSetX11SelectionString(data); + Py_RETURN_NONE; +} + +static PyMethodDef sel_methods[] = { + {"get_selection_x11", (PyCFunction)get_selection_x11, METH_NOARGS, ""}, + {"set_selection_x11", (PyCFunction)set_selection_x11, METH_VARARGS, ""}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + + +#endif + +bool +init_x11_funcs(PyObject *module) { +#ifdef HAS_X11_SELECTION + if (PyModule_AddFunctions(module, sel_methods) != 0) return false; +#endif + return true; +}